Show where the sun is on the sky in real time - how? - javascript

I am using a function from mourner/suncalc that allows me to get the current position of our sun. With getPosition(), I want to create an animation on a image or with pure CSS (scaleable to different screen resolutions and orientations, of course), where you can see where the sun is right now in real time on the page. A totally unnecessary function but a fun function :) The image below illustrates how I am thinking.
Like I said, I'll be using the getPosition() function from mourner's function which prints azimuth and altitude of the sun. The problem I am facing now, is to somehow convert this data to percents or pixels, so the sun in my example image above moves along the round line (and yes, the sun must be blocked by the straight line that imitates the ground), imitating the real position on the sky in real life.
The azimuth data looks like -0.7000179547193575 and the altitude like this: -0.699671080144066 (based on the current sun position where I am right now).
How do I accomplish this? Can I do this with pure CSS or do I have to do it with images?

I don't know the exact formula but here is an idea how you can create this using CSS then you simply have to adjust different values.
var sun = document.querySelector('.sun');
function update() {
var x = Math.random() * 180;
var y = Math.random() * 40;
sun.style.transform="rotateX("+y+"deg) rotate("+x+"deg)"
}
.container {
width:300px;
height:150px;
margin:auto;
overflow:hidden;
border:1px solid;
}
.sun {
margin:20px;
padding-top:calc(100% - 40px);
position:relative;
border-radius:50%;
border:1px solid grey;
transform:rotateX(20deg) rotate(20deg);
background:
linear-gradient(red,red) center/100% 1px;
background-repeat:no-repeat;
transition:1s;
}
.sun:before {
content:"";
position:absolute;
top:calc(50% - 20px);
left:-20px;
width:40px;
height:40px;
background:yellow;
border-radius:50%;
}
<div class="container">
<div class="sun">
</div>
</div>
<button onclick="update()">update</button>
Using the code below you simply need to convert your values to a degrees in order to rotate the sun element and place the sun in the correct place.

Related

Overlay of two images with transparency

I'm looking for a solution in Javascript maybe to create a real-time preview of products based on multiple options that a consumer could choose from multiple radiobutton.
Exemple : I have a face.png and a hat.png with transparents parts, and a cap, and when I click on cap, I would like to display the image of the cap + the face and if I click on the buttonradio on hat, I would like to update my preview in real time and keep the face and only change the image of the hat (a png with transparency)
Do you have any idea how I could do this?
Thanks in advance !
you can use a container div and place face and hat inside of that div then position each other with position absolute
i added a function for changing hats
by clicking the thumbnail of hat user will change the src attribute of the actual hat image which we were showing
let hats = [
"https://m.media-amazon.com/images/I/81B6-uzku8L._UX679_.jpg",
"https://rukminim1.flixcart.com/image/714/857/jiulk7k0/cap/g/r/v/free-hat-peter-india-original-imaf6gzbhh7pydzy.jpeg?q=50",
"https://contents.mediadecathlon.com/p982435/31cf29c7f44e13d3f77af7bd205a303c/p982435.jpg"
];
let currentIndex = 0;
document.addEventListener("DOMContentLoaded",()=>{
let thumpnails = document.querySelector('.thumpnails');
hats.forEach((hat)=> {
let img = document.createElement('img');
img.src = hat;
img.classList.add('thumpnail');
thumpnails.append(img);
img.onclick= ()=>{showMe(hat)};
});
})
function showMe(src){
document.querySelector('.hatImg').src = src;
}
//document.querySelector('#next').addEventListener('click',next)
.pic{
position:relative;
width:200px;
height:300px;
border:1px solid black;
}
.face{
position: absolute;
height: 150px;
width:100px;
background:red;
bottom:25px;
left:50px;
}
.hatImg{
width:180px;
position:absolute;
left:10px;
bottom:100px;
opacity:0.8;
}
.thumpnail{
width:50px;
margin: 0.25rem;
}
<div class="pic">
<div class="face"></div>
<img class="hatImg" src="https://m.media-amazon.com/images/I/81B6-uzku8L._UX679_.jpg">
</div>
<div class="thumpnails"></div>

highlighting characters in text depending on position of page

I have a text on my website that scrolls horizontal through the page. I’m trying to get around 8 characters highlighted in black, while the rest is grey. But those characters are meant to vary as you scroll though, the highlighted bit should remain in place.
In case this doesn’t make any sense, if grey was an x, it should look something like this:
xxxxx xpsum dolox xxx xxxx
xxxx xxsum dolox sxx xxxx
xxx xxxum dolox six xxxx x
xx xxxxm dolox sit xxxx xx
I’m trying to get this done in jQuery, but I can’t get it to work. I also like to say that I’m not at all an expert in webdesign, so I don’t know what I’m doing. Anyway, I’ve tried two different approaches, one is to say “change colour of text when going over an underlying div”. The other approach is to change the colour of the text depending on the scrolling position, but the problem here is that it takes the scrolling position of the whole div, instead of a fixed position on the page. Both don’t work at the moment, examples are here:
jsfiddle 9p29tz2f
jsfiddle 9p29tz2f/1
If anyone has any ideas how to approach this, or needs some more clarification, please let me know. Many thanks!
Clone the text and set it as a child of the overlay box then scroll them together:
$(function(){
var $bodytext = $('#bodytext'),
$clone = $bodytext.clone();
//copy the text and append it to #black:
$clone.attr("id","clone").prependTo("#black");
//scroll #clone with #bodytext:
$bodytext.scroll(function(){
$clone.scrollLeft($bodytext.scrollLeft());
});
});
http://jsfiddle.net/9p29tz2f/2/
I've taken Teemu's solution and modified it a bit: http://jsfiddle.net/9af91wcL/2/
The important bits: The code moves a white DIV (#grey-overlay) on top of the text and makes it transparent. By adding black and white pixels, you get grey. The grey level is determined by the alpha channel (0.7 in the rgba() function).
You need to assign a height or it will look odd. I use 1.5em to make sure it doesn't overlap with the scroll bar of the #bodytext div.
Also make sure that the top/left position of both div's is the same.
In your real code, you can make the horizontal scrollbar disappear and scroll with JavaScript.
HTML
<div id="grey-overlay"></div>
<div id="bodytext">text...</div>
CSS
body {
background: #ffffff;
color: #000000;
font-family: sans-serif;
font-size: 200%;
}
#bodytext {
top: 15%;
width:200px;
height: 2em;
padding: 0;
position:absolute;
overflow-x:scroll;
overflow-y:hidden;
white-space: nowrap;
}
#grey-overlay {
background-color: rgba(255, 255, 255, 0.7);
width:40px;
height: 1.5em;
top:15%;
position:fixed;
z-index: 10;
}
You need to show the same content within #black as in #bodytext, and synchronize its position relative to #bodytext scrolling. This can be achieved by using an extra wrapper around #black. Something like this:
CSS:
#cover {
top: 15%;
height:50%;
width: 120px;
padding: 0;
position:fixed;
overflow-x: hidden;
background-color: #D8D8D8;
}
#black {
color: #000000;
width:100%;
height:100%;
top:0px;
left: 0px;
position:absolute;
white-space: nowrap;
z-index: 10;
}
#bodytext {
top: 15%;
width:100%;
height:85%;
padding: 0;
position:absolute;
overflow-x:scroll;
white-space: nowrap;
color: #D8D8D8;
}
HTML:
<div id="cover">
<div id="black"></div>
</div>
JS:
$(document).ready(function () {
var black = $('#black'),
btext = $('#bodytext');
black.text(btext.text()); // Clone the content
btext.scroll(function () {
var pos = btext.scrollLeft();
black.css('left', -pos + 'px'); // Set the position to match #bodytext
});
});
A live demo at jsFiddle.
Notice, that if you need some left margin, it has also to be "calculated in" to pos.

HTML5 Canvas shape from circle to triangle

I've been looking around and I can't seem to find a clear way in which I can animate a shape to change from a circle to a triangle or to a rectangle or the other way around. I would assume that I could somehow store the shape and change its attributes in order to convert it.
Basically what I am asking is, how can I draw a circle and then animate it to a triangle on the click of a button? Is that possible with canvas shapes?
Thanks!
Here's one approach you can use to animate a circle to-and-from any regular polygon.
Create your triangle (or any regular polygon) using quadratic curves for each side.
That way you can animate the quadratic curve's control point to control the "roundness" of your polygon.
If the control point is on the polygon line, then the curve has zero roundness and the result is your polygon.
If the control point is appropriately outside the polygon line, then the curve approximates the roundness of a circle and the result is your polygon looks like a circle.
To "morph" between circle-polygon, you just animate the control point of the curve.
I use "approximates" to describe the circle because quadratic curves can only approximate a circle. If you want an even better circle, you can refactor my code to use cubic Bezier curves instead of quadratic curves.
Here's example code and a Demo: http://jsfiddle.net/m1erickson/NMJ58/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
// change sideCount to the # of poly sides desired
//
var sideCount=3;
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.lineWidth=2;
ctx.fillStyle=randomColor();
var PI2=Math.PI*2;
var cx=150;
var cy=150;
var radius=100;
var xx=function(a){return(cx+radius*Math.cos(a));}
var yy=function(a){return(cy+radius*Math.sin(a));}
var lerp=function(a,b,x){ return(a+x*(b-a)); }
var sides=[];
for(var i=0;i<sideCount;i++){
sides.push(makeSide(i,sideCount));
}
var percent=0;
var percentDirection=0.50;
$("#toShape").click(function(){
percentDirection=-0.50;
})
$("#toCircle").click(function(){
percentDirection=0.50;
})
animate();
// functions
function animate(){
requestAnimationFrame(animate);
drawSides(percent);
percent+=percentDirection;
if(percent>100){percent=100;}
if(percent<0){percent=0;}
}
function drawSides(pct,color){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(pct==100){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,PI2);
ctx.closePath();
ctx.fill();
}else{
ctx.beginPath();
ctx.moveTo(sides[0].x0,sides[0].y0);
for(var i=0;i<sideCount;i++){
var side=sides[i];
var cpx=lerp(side.midX,side.cpX,pct/100);
var cpy=lerp(side.midY,side.cpY,pct/100);
ctx.quadraticCurveTo(cpx,cpy,side.x2,side.y2);
}
ctx.fill();
}
}
function makeSide(n,sideCount){
var sweep=PI2/sideCount;
var sAngle=sweep*(n-1);
var eAngle=sweep*n;
var x0=xx(sAngle);
var y0=yy(sAngle);
var x1=xx((eAngle+sAngle)/2);
var y1=yy((eAngle+sAngle)/2);
var x2=xx(eAngle);
var y2=yy(eAngle);
var dx=x2-x1;
var dy=y2-y1;
var a=Math.atan2(dy,dx);
var midX=lerp(x0,x2,0.50);
var midY=lerp(y0,y2,0.50);
var cpX=2*x1-x0/2-x2/2;
var cpY=2*y1-y0/2-y2/2;
return({
x0:x0, y0:y0,
x2:x2, y2:y2,
midX:midX, midY:midY,
cpX:cpX, cpY:cpY,
color:randomColor()
});
}
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}); // end $(function(){});
</script>
</head>
<body>
<button id="toShape">Animate to Shape</button>
<button id="toCircle">Animate to Circle</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
You might want to use Raphael (https://dmitrybaranovskiy.github.io/raphael/) or a similar library to take care of this for you. The raphael site contains many examples similar to the case you describe.
It is hard to understand your exact aim and what kind of animation you need between shapes as you don't specify animation steps/states. But you could take a look at CSS3 transitions.
I made a few in the following demo that illustrate how you can simulate "shape morphing" (is this the corect term?) if that is what you are trying to do :
DEMO (click on the circles to animate them)
For the circle to rectangle, the transition is pretty easy to achieve, you just need to animate border-radius :
CSS :
#rec {
float:left;
width:200px;
height:200px;
background:gold;
border-radius:50%;
-webkit-transition: border-radius 1s, width 1s;
cursor:pointer;
}
#rec.animate {
border-radius:0%;
width:300px;
}
For the circle to triangle, the shape transition is a bit harder to achieve, the shape morphing isn't perfect and needs improvement but you can get the idea.
The circle and the triangle are set with pseudo elements and animations display one or the other with 2 different transitions :
CSS :
/*CIRCLE TO TRIANGLE 1 */
#tr1{
float:right;
position:relative;
cursor:pointer;
width:200px;
height:200px;
}
#tr1:before, #tr1:after{
content:'';
position:absolute;
}
#tr1:before{
top:0; left:0;
background:gold;
border-radius:50%;
width:100%;
height:100%;
-webkit-transition: width 1s, height 1s, left 1s, top 1s;
}
#tr1:after{
left:50%;
top:50%;
border-left:0px solid transparent;
border-right:0px solid transparent;
border-bottom:0px solid gold;
-webkit-transition: border-left 1s, border-right 1s, border-bottom 1s,left 1s, top 1s;
}
#tr1.animate:before{
width:0;
height:0;
top:50%; left:50%;
}
#tr1.animate:after{
top:0; left:0;
border-left:100px solid transparent;
border-right:100px solid transparent;
border-bottom:200px solid gold;
}
/*CIRCLE TO TRIANGLE 2 */
#tr2{
float:right;
position:relative;
cursor:pointer;
width:200px;
height:200px;
}
#tr2:before, #tr2:after{
content:'';
position:absolute;
}
#tr2:before{
top:0; left:0;
background:gold;
border-radius:50%;
width:100%;
height:100%;
-webkit-transition: width 1s, height 1s, left 1s, top 1s;
}
#tr2:after{
left:20px;
top:0;
border-left:80px solid transparent;
border-right:80px solid transparent;
border-bottom:160px solid gold;
-webkit-transition: border-left 1s, border-right 1s, border-bottom 1s,left 1s, top 1s;
z-index:-1;
}
#tr2.animate:before{
width:0;
height:0;
top:50%; left:50%;
}
#tr2.animate:after{
top:0; left:0;
border-left:100px solid transparent;
border-right:100px solid transparent;
border-bottom:200px solid gold;
}
( I will award #rje because he got me in the right direction and after all the effort I realized that my question wasn't detailed enough with the specifics of my issue ).
First I will explain what I was actually looking for: Basically when creating a "shape" in a canvas context it's pretty easy to use that as a mask, by mask I mean, let's say you draw a circle in the middle of the canvas which remains transparent but the canvas is filled with a certain color.
Using raphael js directly is kind of strange to do this until you get the hang of it because it's actually svg and there are different rules. You have to draw a outer path which will match the paper ( the raphael "canvas" ) and an inner path which will remain transparent. The challenge for me was to make it also responsive But I managed to do it after all using something like this
var tw; // canvas width
var th; // canvas height
var tr; // radius of circle, in my case calculated dynamically smth like (th - 20) / 2
var outerpath = "M0,0L" + tw + ",0L" + tw + "," + th + "L0," + th + "L0,0z";
var innerpath = "M" + (tw/2) + "," + (th/2 - tr) + "A" + tr + "," + tr + " 0 1,0 " + (tw/2 + 0.1) + "," + (th/2 - tr) + "z";
var path = outerpath + innerpath;
var mask = paper.path(path).attr({'stroke': 0, 'fill' : '#ccc', 'fill-opacity' : 0.9});
The great thing about this is that using Raphael you can animate them and also use for example innerpath for creating another shape and use another color to fill that. Amazing.
Thanks everybody.

Change element-class on click, more elegant solution

I'm using some of my spare time to learn som basic programming and I've hit kind of a bump.
The following script works, but it's not elegant, at all, and I suspect that It can be solved with far less code.
<div class="naal brukbar" id="naal_1" onclick="writeText(brukbar); byttKlasse_1();"></div>
<div class="naal circus" id="naal_2" onclick="writeText(circus); byttKlasse_2();"></div>
In this case it is a map, with pins located trough CSS-coordinators. The above is the default.
The "problem" if you can call it that, is that i got more than 20 pins, and therfore the pin-class-changing-javascript seems unnecessary long and residual.
JS:
function byttKlasse_1()
{
document.getElementById("naal_1").className = "over brukbar";
document.getElementById("naal_2").className = "naal circus";
document.getElementById("naal_5").className = "naal micro";
document.getElementById("naal_6").className = "naal disko";
document.getElementById("naal_7").className = "naal lundgreen";
document.getElementById("naal_8").className = "naal kos";
document.getElementById("naal_9").className = "naal raus";
document.getElementById("naal_10").className = "naal mormors";
document.getElementById("naal_11").className = "naal samfundet";
}
I need 25 + 1 of these (25 for the pins onclick and one for the reset once the site reloads)
Don't know if it's relevant, but here is the -
CSS:
.naal {
position: relative;
background-image: url('bilder/naal.png');
width:12px;
height:20px;
opacity:1;
}
.over {
position: relative;
background-image: url('bilder/naal_aktiv.png');
width:12px;
height:20px;
opacity:.9;
cursor:pointer;
}
.brukbar {top: -270px; left: 285px;}
.circus {top: -450px; left: 368px;}
Is it possible to "array it up" somehow? I can't just change one class, due to the pins relative location on the map.
something like that? (i tested only in chrome)
js
var current='x';
function smallBoxesHandler(e){
if(current!='x'){
bigBox.childNodes[current].classList.remove('checked');
}
current=Array.prototype.slice.call(e.target.parentNode.childNodes).indexOf(e.target);
bigBox.childNodes[current].classList.add('checked');
}
var bigBox=document.createElement('div');
bigBox.addEventListener('click',smallBoxesHandler,false);
document.body.appendChild(bigBox).innerHTML=new Array(11+1).join('<div></div>');
css
body>div{
width:220px;
border:1px solid rgba(0,0,0,0.5);
overflow:auto;
}
body>div>div{
width:20px;
height:20px;
float:left;
box-sizing:border-box;
}
body>div>div:hover{
border:1px dotted rgba(0,255,0,0.5);
}
body>div>div.checked{
border:1px dotted rgba(0,255,0,0.5);
background-color:red;
}
example
http://jsfiddle.net/bg2Hw/
EDIT
with extra styles....
http://jsfiddle.net/bg2Hw/1/
or
http://jsfiddle.net/bg2Hw/2/ , http://jsfiddle.net/bg2Hw/3/

How to align a label to the top middle of the div control and draw a rectangle around it?

I have a label inside a div control.I want to align it to the top middle of the div control and draw a rectangle around that text.And also i want to display the characters of that label's text one by one from left to right .
How do i achieve this ?
Well to center the text to the middle of the div horizontal, you simply need to style it with
div#ctrl {
text-align: center
}
To have a rectangle around the text, you need to define a border, probably with padding and margin:
div#ctrl span {
border: 1px #333 solid;
padding: 5px;
}
You need to use javascript to animate the text, made easier with jQuery. Here a link to working example I whipped of what you were looking for:
http://jsfiddle.net/5QdPh/
In the future try to do a little more research and ask questions about specific problems that have not been answered before. All of this is basic, well documented stuff.
Here you go for the first part:
http://fiddle.jshell.net/VdmFV/
Fot the second part you'd need some fancy javascript / jQuery which you should attempt yourself first then come back here for pointers.
<style>
#control {
width:200px;
height:200px;
background:#ddd;
text-align: center
}
#label {
border:1px solid red;
}
</style>
<div id='control'>
<span id='label'></span>
</div>
<script>
var label = document.getElementById("label");
var msg = "Message";
var i = 0;
var interval = setInterval( function() {
label.innerHTML = msg.substr(0,i);
i++;
if ( i == msg.length ) {
clearInterval(interval);
}
}, 1000)
</script>

Categories

Resources