Background color change on mouse move - javascript

I have found this pen on codepen. I would like to use this effect, but in a grayscale.
Could anyone help me?
Thanks in advance!
// Create a HTML div Element called 'page'
var page = document.createElement('DIV');
// Gives the page variable full height
page.style.height = '100vh';
// Applies the page element to the document(web page)
document.body.appendChild(page);
//Creates variables for x & y for know where our mouse is
//x is for horizontal values, and y for vertical ones
var x = 0;
var y = 0;
// Add Event Listener for page. Listens for any mouse movement
// inside the page element. If found, run function below
page.addEventListener('mousemove', function(event) {
//Takes the mouse movement we listened for and saves it into two variables
x = event.clientX;
y = event.clientY;
//Here we set the background color to the x & y value that the mouse has over the web page. See css part for rgb explaination
page.style.backgroundColor = 'rgb(' + x + ', ' + y + ', 100)';
//By writing variable + ', ' we combine the value with text to make it write like rgb(x, y, 100); when sent to style part (css)
//Adds a text element to the page. It writes out the x & y value
page.textContent = x + ', ' + y;
});
// Find the css element called 'box' to use in future
var box = document.getElementById('box');
//Function for a box that follows the mouse around
var mousebox = function() {
//Calls the css code to push the box away from the left & top
//the same x & y values that the mouse has
box.style.left = x + 'px';
box.style.top = y + 'px';
}
// Find the css element called 'rbox' to use in future
var rbox = document.getElementById('rbox');
//Variable to hold our current angle/degree of rbox
var degree = 0;
//Setup a rotating box in the center
var rotatebox = function(){
//Adds rotation, but makes it go (357, 358, 359, 0, 1, 2)
degree = (degree + 1) % 360;
//adds the current rotation to the rbox
rbox.style.transform = 'rotate('+degree+'deg)';
//Pushes the box from left & top by half of window width & height
rbox.style.left = window.innerWidth / 2 + 'px';
rbox.style.top = window.innerHeight / 2 + 'px';
}
//Sets up an update interval of how often both boxes happen. Number is in milliseconds so 100ms = 10 times per second
setInterval(mousebox,100);
setInterval(rotatebox,10);
body {
margin: 0; /* Removes any margin so anything within the body fills the space */
}
/* Box that will follow the mouse around */
#box {
position: absolute; /* Allows us to move it around */
color: #FFF; /* Makes the text white */
font-size: 24px; /* Makes the box text larger (24 pixels tall) */
transition: ease-out 1s; /* Gives a smooth movement following the box, s for seconds. Feel free to increase lower */
}
/* Rotating box that will spin in the middle */
#rbox {
position: absolute; /* Allows us to move it around */
width: 50px; /* Size with width/height */
height: 50px;
background-color: #FFF; /* Makes the background white, if removed its transparent. If all are the same you can write just 3, but otherwise hexagon letter/numbers come in 6 */
/* When talking RGB colour, 0 or 00 gives no colour (black) while 255 or FF is full colour */
/* RGB: For red #FF0000 , green is #00FF00 , and blue is #0000FF. Inbetween these you can mix and match*/
/* Use to find specific colours you like https://www.w3schools.com/colors/colors_picker.asp */
color: #000; /* Text in the box is black */
text-align: center; /* Puts the text in middle */
font-size: 36px; /* Text size, fits the size we set above */
}
<div id="box">Hello!</div>
<div id="rbox">:)</div>

Just use a single variable in all three color's places, i.e rgb(x, x, x)
var page = document.createElement('DIV');
page.style.height = '100vh';
document.body.appendChild(page);
var x = 0;
var y = 0;
page.addEventListener('mousemove', function(event) {
x = event.clientX;
y = event.clientY;
// ================== Solution ======================
Gray = y; // or Math.min(x, y) or (x + y) / 2
color = [Gray, Gray, Gray].join(", ");
page.style.backgroundColor = 'rgb(' + color + ')';
// =====================================================
page.textContent = x + ', ' + y;
});
var box = document.getElementById('box');
var mousebox = function() {
box.style.left = x + 'px';
box.style.top = y + 'px';
}
var rbox = document.getElementById('rbox');
var degree = 0;
var rotatebox = function() {
degree = (degree + 1) % 360;
rbox.style.transform = 'rotate(' + degree + 'deg)';
rbox.style.left = window.innerWidth / 2 + 'px';
rbox.style.top = window.innerHeight / 2 + 'px';
}
setInterval(mousebox, 100);
setInterval(rotatebox, 10);
body {
margin: 0;
/* Removes any margin so anything within the body fills the space */
}
/* Box that will follow the mouse around */
#box {
position: absolute;
/* Allows us to move it around */
color: #FFF;
/* Makes the text white */
font-size: 24px;
/* Makes the box text larger (24 pixels tall) */
transition: ease-out 1s;
/* Gives a smooth movement following the box, s for seconds. Feel free to increase lower */
}
/* Rotating box that will spin in the middle */
#rbox {
position: absolute;
/* Allows us to move it around */
width: 50px;
/* Size with width/height */
height: 50px;
background-color: #FFF;
/* Makes the background white, if removed its transparent. If all are the same you can write just 3, but otherwise hexagon letter/numbers come in 6 */
/* When talking RGB colour, 0 or 00 gives no colour (black) while 255 or FF is full colour */
/* RGB: For red #FF0000 , green is #00FF00 , and blue is #0000FF. Inbetween these you can mix and match*/
/* Use to find specific colours you like https://www.w3schools.com/colors/colors_picker.asp */
color: #000;
/* Text in the box is black */
text-align: center;
/* Puts the text in middle */
font-size: 36px;
/* Text size, fits the size we set above */
}
<div id="box">Hello!</div>
<div id="rbox">:)</div>
Explanation
There are several ways of converting RGB to Gray Scale, but none of them apply in this case. Take a look at all of them here: Gray Scale Algorithms
Using a single variable say rgb(y, y, y) works because, gray scale colors generally appear like this: #d3d3d3, rgb(63,63,63), etc. A single value in all channels
If you want to use both the variables, you can do Math.min(x, y) or (x + y) / 2 and then pass it to a variable Gray, which then can be set like so: rgb(Gray, Gray, Gray)
color = [Gray, Gray, Gray].join(", "), this just joins the values separated by comma, in order to avoid writing comma manually.

Change this line:
//Here we set the background color to the x & y value that the mouse has over the web page. See css part for rgb explaination
page.style.backgroundColor = 'rgb(' + x + ', ' + y + ', 100)';
To this
page.style.backgroundColor = 'grayscale(rgb(' + x + ', ' + y + ', 100))';

Related

How to find out if an object is touching another object in JS

(excuse my bad english, I am 13 years old)
alright, even though i just joined stackoverflow today, I have been coding for a while. I'm trying to make a simple game (and may make it something bigger later) and I want the hammer (the player sprite) not be able to go through the box toward the middle of the screen, but I don't know how. here is what I have:
var sq = document.getElementById("box");
var posX = 0;
var posY = 0;
var rot = "rotate(0deg)";
var id = null;
function move(object, pixels, xa){
if(xa == true) {
posX+=pixels;
object.style.left = posX + 'px';
}else{
posY+=pixels;
object.style.top = posY + 'px';
}
}
OBJect.style.left = "200px";
OBJect.style.top = "200px";
document.addEventListener('keydown', logKey);
function logKey(e) {
if (`${e.code}` == "ArrowRight") {
rot = "rotate(90deg)";
sq.style.transform = rot;
move(sq, 5, true);
if(posX > 470){
posX = 5;
}
}
if (`${e.code}` == "ArrowLeft") {
rot = "rotate(270deg)";
sq.style.transform = rot;
move(sq, -5, true);
if(posX < 0){
posX = 465;
}
}
if (`${e.code}` == "ArrowDown") {
rot = "rotate(180deg)";
sq.style.transform = rot;
move(sq, 5, false);
if(posY > 465){
posY = 5;
}
}
if (`${e.code}` == "ArrowUp") {
rot = "rotate(0deg)";
sq.style.transform = rot;
move(sq, -5, false);
if(posY < 0){
posY = 470;
}
}
}
setInterval(function(){
xaxis.innerHTML = "x: " + posX;
yaxis.innerHTML = "y: " + posY;
rotate.innerHTML = rot;
},1);
#myContainer {
width: 500px;
height: 500px;
position: relative;
background: black;
outline: red solid 10px;
}
#box {
width: 30px;
height: 30px;
position: absolute;
background-color: gray;
}
#OBJect {
width: 30px;
height: 30px;
position: absolute;
background-color: gray;
}
<!DOCTYPE html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<style>
/*style would go here/*
</style>
<body>
<div id="myContainer">
<img src="https://cdn.glitch.com/7f9c2ae2-9b45-42a1-a387-380de7f5d3bd%2Fhammer.png?v=1615308683807" alt="hammer" id="box">
<div id="OBJect"></div>
</div>
<br><br>
<div id="xaxis"></div>
<div id="yaxis"></div>
<div id="rotate"></div>
<script>
//script would go here
</script>
</body>
</html>
yeah, yeah, I know. I could definetly improve, but I only know basic things,and some of these from either Stackoverflow or w3schools, and yes, I know there is a lot of solved answers with this problem, but I get confused by them because they are too complicated for me. I just request easy, simple code to understand (if it isn't, please label things so I know).
sorry if this is too much, I just need help :/
so to do this you need to know the 4 corners of each element then you need to check if the other object is within the players bounds
they're both rectangles and to be touching 1 of these statements have to be true
the top left corner of the square is to the right of the top left corner of the player and the top left corner of the square is to the left of the top right corner of the player while the top left corner of the square is less than the y of the top side and higher than the y of the bottom side
the top right corner of the square is to the left of the top right corner of the player and the top right corner of the square is to the right of the top left corner of the player while the top right corner of the square is less than the y of the top side and higher than the y of the bottom side
same as 1 & 2 but with the bottom left and right corners
if one of the corners has the same x and y as a corner on the other object or if the position of one object is the same as the other
a second way to do this is using Pythagoras theorem to get the distance between two points
a^2 + b^2 = c^2
how that would look in code
let c = Math.sqrt(Math.pow(Math.abs(x1 - x2), 2) + Math.pow(Math.abs(x2, y2), 2))
this is a little tricky but the distance between two points is a triangle in a sense so the distance on x and y form the two legs then to get the actual distance we need the hypotenuse which is what Pythagoras theorem gets us. So to get a and b we need to get the absolute value of the first minus second x and y to get the distance on x and y then we square them with Math.pow() and add them but that gives us c^2 and we just want c so we get the square root with Math.sqrt() which gives us the distance then the one other thing we have to do is get the center of the objects to use as a and b. Since you're working with javascript on a webpage the X and Y values are for the top left corner so you need to add half the width and height to x and y appropriately to get the center of the object, then you can use the distance formula. the only problem with this approach is that it works best for circles because every point around the edge is equally distant from the center which isn't true for a square.
So personally I would use the first method, you can get the other corners by using width and height to add to the position of the top left corner to get the other positions. it's more code but more precise than distance because you're checking the bounds of each object rather than checking distance from center
I also joined today and I am 12. since the hammer is an img, you can use css:
I think your question was that you want to move the hammer, if yes:
var left = 0; /*left and top can be edited in your code but*/
var top = 0;/*you have to reset them using the code below*/
var hammer = document.querySelector('#hammer');
hammer.style.left = left + 'px';
hammer.style.top = top + 'px';
#hammer {
position: absolute;
left: 0px;
right: 0px;
}/*set left and right via js*/
<!--just add an id like #hammer to the hammer-->

arranging <div>s around a polygon (HTML, css, .ejs)

I want to arrange some rectangular div components around a regular polygon. Basically one of the long sides of the divs will be coincident with a line segment around the polygon.
In the final code, I'll use .ejs (since the number of sides of the polygon is dynamic, 3-10 sides). In my "quick and dirty" testing I'm doing a triangle in just HTML and CSS to get the math right.
I have a "very close" solution already and am wondering how to get it "exact" and am also wondering why my geometry intuition is so far off.
HTML and CSS:
div {
position: absolute;
left: 200px;
top: 200px;
width: 80px;
height: 40px;
background-color: skyblue;
}
.rotatedA {
transform: translateY(-60px) translateX(-35px) rotate(300deg);
background-color: blue;
}
.rotatedB {
transform: translateY(-60px) translateX(35px) rotate(60deg);
background-color: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>title</title>
<link rel="stylesheet" href="basic.css">
</head>
<body>
<div>Normal</div>
<div class="rotatedA">Rotated</div>
<div class="rotatedB">Rotated</div>
</body>
</html>
The first attempt I rotated "A" by 60 and "B" by -60 and did a translateY equal to the div height. When that did not work I played around with it.
On this last attempt (close but not perfect since the rotations won't give an integer) it seems like the Y adjustment is 1.5x (item height + cos(60)) but the X adjustment is 1/2 of sin(60) (I don't understand why).
Since my results aren't going to be an integer number of pixels what is the correct way to do this? Also, I don't understand why my geometry is so off (I could understand sin(60) but 1/2(sin(60)) doesn't make sense to me
Here's a mathematical way; the number and dimensions are read by the script, then the divs are arranged accordingly. I also made sure that the wrapper container has the correct dimensions so it can be used with other elements:
function arrange(wrapper) {
wrapper.style.position = "relative";
const rects = Array.from(wrapper.children);
const n = rects.length;
/* dimensions of a rectangle */
const bb = rects[0].getBoundingClientRect();
const a = bb.width;
const h = bb.height;
/* incircle radius of regular polygon */
const r = a * 0.5 / Math.tan(Math.PI / n);
/* radius of outer circle */
const bigR = Math.sqrt((r + h) * (r + h) + a * a / 4);
rects.forEach((rect, i) => {
const angle = i * (360 / n);
if (angle) rect.style.transform = `rotate(${angle}deg)`;
rect.style.position = angle ? "absolute" : "relative";
rect.style.marginBottom = bigR + r + "px";
rect.style.transformOrigin = `${a/2}px ${-r}px`;
rect.style.left = bigR - a / 2 + "px";
rect.style.top = bigR + r + "px";
});
if (window.getComputedStyle(wrapper).display == "inline-block")
wrapper.style.width = 2 * bigR + "px";
}
arrange(document.querySelector('#polygon'));
#polygon {
border: 1px solid black;
display: inline-block;
}
#polygon div {
width: 80px;
height: 20px;
background-color: skyblue;
text-align: center;
padding: 5px;
}
<div id="polygon">
<div>Normal</div>
<div>Rotated</div>
<div>Rotated</div>
<div>Rotated</div>
<div>Rotated</div>
<div>Rotated</div>
<div>Rotated</div>
</div>
The basic idea is to
calculate the in-circle's radius of the polygon based on the width of a rectangle
set transform-origin accordingly centered and above the first rectangle
arrange the others by rotating them
(do more calculations so the wrapper element encompasses everything exactly)

Turn list into polygon that scales

I have used latex and in particular tikz quite a bit. Using this I was able to create the image shown below.
The following short code was used to create the image.
\documentclass[tikz]{standalone}
\begin{document}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{backgrounds}
\begin{tikzpicture}[background rectangle/.style={fill=black},
show background rectangle]
\def\pages{
Home,
Events,
Pictures,
Video,
Contact,
About,
Map
}
\def\ngon{7}
\node[regular polygon,regular polygon sides=\ngon,minimum size=3cm] (p) {};
\foreach\page [count=\x] in \pages{\node[color=white, shift={(\x*360/7+35:0.4)}] (p\x) at (p.corner \x){\page};}
\foreach\i in {1,...,\numexpr\ngon-1\relax}{
\foreach\j in {\i,...,\x}{
\draw[thin, orange, dashed] (p\i) -- (p\j);
}
}
\end{tikzpicture}
\end{document}
I have tried for the last few hours to recreate the same image using 'HTMLæ, 'CSS' and 'Javascript'. I used the 'canvas' element to draw the lines, however I ran into a series of problems as can be seen in the image below
Which was made with the following code. I tried to the best of my abilities to minimize the code. The code can be found at the bottom of the post. The code has the following problems
Scalability. The text in the image is not the same as in the 'body' of the page.
The image hides the rest of the text in the body
To place the text outside the figure is hardcoded
The last minor problem is that the first element in the list is not drawn
I would like to address the problems above, but I am unsure how to proceed. Again I am not married to the idea of using canvas (can a better result be done using nodes and elements instead). However, the output should mimic the first image as closely as possible.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Canvas octagon</title>
<style>
* {
margin: 0;
padding: 0;
color:white;
background:black;
}
canvas {
display: block;
}
html,
body {
width: 100%;
height: 100%;
margin: 0px;
border: 0;
overflow: hidden;
/* Disable scrollbars */
display: block;
/* No floating content on sides */
}
</style>
</head>
<body>
<canvas id="polygon"></canvas>
<h2>more space</h2>
<ol id="poly">
<li>About</li>
<li>Home</li>
<li>Pictures</li>
<li>Video</li>
<li>Events</li>
<li>Map</li>
<li>Apply?</li>
<li>Recepies</li>
</ol>
some more text here
<script>
(function() {
var canvas = document.getElementById('polygon'),
context = canvas.getContext('2d');
// resize the canvas to fill browser window dynamically
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
/**
* Your drawings need to be inside this function otherwise they will be reset when
* you resize the browser window and the canvas goes will be cleared.
*/
drawStuff();
}
resizeCanvas();
function drawStuff() {
// do your drawing stuff here
context.beginPath();
context.translate(120, 120);
context.textAlign = "center";
var edges = document.getElementById("poly").getElementsByTagName("li");
var sides = edges.length
var angle = (Math.PI * 2) / sides;
var radius = 50;
context.save();
for (var i = 0, item; item = edges[i]; i++) {
console.log("Looping: index ", i, "item " + item.innerText);
var start_x = radius * Math.cos(angle * i);
var start_y = radius * Math.sin(angle * i);
context.lineTo(start_x, start_y);
var new_x_text = 1.4 * radius * Math.cos(angle * i);
var new_y_text = 1.4 * radius * Math.sin(angle * i);
context.fillText(item.innerText, new_x_text, new_y_text);
context.strokeStyle = 'orange';
for (var j = 0; j < i; j++) {
var new_x = radius * Math.cos(angle * j);
var new_y = radius * Math.sin(angle * j);
context.moveTo(start_x, start_y);
context.lineTo(new_x, new_y);
console.log(new_x, new_y);
}
context.fillStyle = 'white'
}
var new_x = radius * Math.cos(0);
var new_y = radius * Math.sin(0);
context.lineTo(new_x, new_y);
context.stroke();
}
})();
</script>
</body>
</html>
Using the canvas to render content
First I will say that using javascript will be longer than if you use some symbolic representation language like Latex. It is designed to do graphical representations with the minimum of fuss. The actual code base that makes it work is substantial but hidden for the general user.
Using the DOM
As the content for the canvas is stored in the DOM it also a good idea to store as much information as you can in the DOM, the colors, fonts, etc can all be stored in an element`s dataset.
For this I have put the settings in the ordered list. It contains all the settings, but there is also a default set of settings in the rendering function. The elements dataset will overwrite the defaults, or you can not add any dataset properties and let it all use the defaults.
Vetting settings
In the example below I have only put a minimum of vetting. People tend to put quotes around everything in the DOM as numbers can sometimes not work if represented as a string, I force all the numbers to the correct type. Though to be safe I should have checked to see if indeed they are valid numbers, the same for the other settings. I have just assumed that they will be correctly formatted.
The function
All the work is done in a function, you pass it the query string needed to find the list and canvas. It then uses the list items to render to the canvas.
Relative sizes
As the canvas size is not always known (it could be scaled via CSS) you need to have some way to specify size independent of pixels. For this I use a relative size. Thus the font size is as a fraction of the canvas size eg data-font-size = 16 means that the font will be 1/16th of the canvas height. The same for the line width, and the dash size is a multiple of the line width. eg data-line-dash = 4 means that the dashes are 4 times the length of the line width.
Element's data properties
To use data set you add the property to the element in the HTML prefixed with the word data- then the property name/s separated by "-". In javascript you can not use "-" directly as part of a variable name (it's a subtract operator) so the property names are converted to camelcase (the same as CSS properties), and stored in the element's dataset property.
<!-- HTML -->
<div id="divElement" data-my-Value = "some data"></div>
<script>
// the property of divElement is available as
console.log(divElement.dataset.myValue); // output >> "some data"
</script>
Scaling & rendering
The canvas is rendered at a ideal size (512 in this case) but the transform is set to ensure that the render fits the canvas. In this example I scale the x and y axis) the result is that the image does not have a fixed aspect.
Background
The canvas is transparent by default, but I do clear it in case you rerender to it. Anything under the canvas should be visible.
I first render the lines, then the text, clearing a space under the text to remove the lines. ctx.clearRect ensure the a canvas rect is transparent.
Drawing lines
To draw the lines you have two loops, From each item you draw a line to every other item. You don't want to draw a line more than once, so the inner loop starts at the current outer loops position + 1. This ensures a line is only rendered one.
Example
The example shows what I think you are after. I have add plenty of comments, but if you have questions do ask in the comments below.
I assumed you wanted the ordered list visible. If not use a CSS rule to hide it, it will not affect the canvas rendering.
Also if you size the canvas via CSS you may get a mismatch between canvas resolution and display size. This can result in blurred pixels, and also some high res displays will set canvas pixels to large. If this is a problem there are plenty of answers on SO on how to deal with blurred canvas rendering and hi res displays (like retina).
function drawConnected(listQ, canvasQ) {
const list = document.querySelector(listQ);
if(list === null){
console.warn("Could not find list '" + listQ +"'");
return;
}
const canvas = document.querySelector(canvasQ);
if(canvas === null){
console.warn("Could not find canvas '" + canvasQ + "'");
return;
}
const ctx = canvas.getContext("2d");
const size = 512; // Generic size. This is scaled to fit the canvas
const xScale = canvas.width / size;
const yScale = canvas.height / size;
// get settings or use dsefault
const settings = Object.assign({
fontSize : 16,
lineWidth : 128,
lineDash : 4,
textColor : "White",
lineColor : "#F90", // orange
startAngle : -Math.PI / 2,
font : "arial",
}, list.dataset);
// calculate relative sizes. convert deg to randians
const fontSize = size / Number(settings.fontSize) | 0; // (| 0 floors the value)
const lineWidth = size / Number(settings.lineWidth) | 0;
const lineDash = lineWidth * Number(settings.lineDash);
const startAngle = Number(settings.startAngle) * Math.PI / 180; // -90 deg is top of screen
// get text in all the list items
const items = [...list.querySelectorAll("li")].map(element => element.textContent);
// Set up the canvas
// Scale the canvas content to fit.
ctx.setTransform(xScale,0,0,yScale,0,0);
ctx.clearRect(0,0,size,size); // clear as canvas may have content
ctx.font = fontSize + "px " + settings.font;
// align text to render from its center
ctx.textAlign = "center";
ctx.textBaseline = "middle";
// set the line details
ctx.lineWidth = lineWidth;
ctx.lineCap = "round";
ctx.setLineDash([lineDash, lineDash]);
// need to make room for text so calculate all the text widths
const widths = [];
for(let i = 0; i < items.length; i ++){
widths[i] = ctx.measureText(items[i]).width;
}
// use the max width to find a radius that will fit all text
const maxWidth = Math.max(...widths);
const radius = (size/2 - maxWidth * 0.6);
// this function returns the x y position on the circle for item at pos
const getPos = (pos) => {
const ang = pos / items.length * Math.PI * 2 + startAngle;
return [
Math.cos(ang) * radius + size / 2,
Math.sin(ang) * radius + size / 2
];
};
// draw lines first
ctx.strokeStyle = settings.lineColor;
ctx.beginPath();
for(let i = 0; i < items.length; i ++){
const [x,y] = getPos(i);
for(let j = i+1; j < items.length; j ++){
const [x1,y1] = getPos(j);
ctx.moveTo(x,y);
ctx.lineTo(x1,y1);
}
}
ctx.stroke();
// draw text
ctx.fillStyle = settings.textColor;
for(let i = 0; i < items.length; i ++){
const [x,y] = getPos(i);
ctx.clearRect(x - widths[i] * 0.6, y - fontSize * 0.6, widths[i] * 1.2, fontSize * 1.2);
ctx.fillText(items[i],x,y);
}
// restore default transform;
ctx.setTransform(1,0,0,1,0,0);
}
// draw the diagram with selector query for ordered list and canvas
drawConnected("#poly","#polygon");
* {
margin: 0;
padding: 0;
color:white;
background:black;
}
canvas {
display: block;
}
html,
body {
font-family : arial;
width: 100%;
height: 100%;
margin: 0px;
border: 0;
display: block;
}
<canvas id="polygon" width = "256" height = "256"></canvas>
<h2>more space</h2>
<ol id="poly"
data-font-size = 16
data-line-width = 128
data-line-dash = 2
data-text-color = "white"
data-line-color = "#F80"
data-start-angle = "-90"
data-font = "arial"
>
<li>About</li>
<li>Home</li>
<li>Pictures</li>
<li>Video</li>
<li>Events</li>
<li>Map</li>
<li>Apply?</li>
<li>Recepies</li>
</ol>

How to map color with the dynamic data

I have an array of time, color in hex (which goes from blue to yellow) and a data array. I want to assign color to each data at the time that it was received. The min value will have yellow color and the max blue. So its a range. The values in the data array are dynamic.
For eg at time 07:00 am, the data received is 47 then the color will light yellow (hex).
Could anyone of you provide me an example on how to code this in javascript? Thanks!
I assume that given your minimum and maximum values that you can find the current value percentage. Something like 100 * (current - min) / (max - min) should give you a number (when rounded) between 0 and 100. This number can then be used in the same way that the color variable is set in the demo below to give you a color between yellow and blue.
Rather than blend through white, you could also blend through green. That would be a matter of choice I guess. If you wanted to do that then I can update the color formula or you can probably figure it out yourself.
I updated the demo with a blend through green. There is too much green in my opinion but you can adjust the color as you like using a formula that biases yellow and blue rather than a linear blend.
var parent = document.getElementById("gradients");
for (var i = 0; i<100; i++){
var color = (i < 50) ? "hsl(60, 100%, " + (50 + i) + "%)" : "hsl(220, 100%, " + (150 - i) + "%)"
var el = document.createElement("div");
el.style.backgroundColor = color;
parent.appendChild(el);
}
var parent2 = document.getElementById("gradients2");
for (var i = 0; i<100; i++){
var color = "hsl(" + (55 + 1.5*i) + ", 100%, 50%)";
var el = document.createElement("div");
el.style.backgroundColor = color;
parent2.appendChild(el);
}
#gradients, #gradients2 { border: solid 1px; margin-bottom: 1em; }
#gradients div { height: 1px; }
#gradients2 div { height: 1px; }
<div id="gradients"></div>
<div id="gradients2"></div>

Create div overlay for image based on xml attributes

I want to create a div overlay, set at 5% opacity, which creates a diagonal bounding box around each of the lines of text in this image. I have the coordinates of each of the four points I need to draw the bounding box, which are encoded as attributes in an XML element which contains the text of individual line as its data. It seems to me that since I have the x,y coordinates for the four corners, I should be able to create the overlay -- but I cannot figure out what the proper syntax would be to mark out the div. Someone suggested to me using the transform functions for CSS (which was the right call as I originally framed this question) but that sounds like I'd be basically writing eight separate pieces of css, one for each line -- which could get messy since there are potentially 118 pictures like this that I would be writing custom pieces of CSS for.
Am I wrong in thinking this can be done programmatically, and if not can someone point me at some methods for doing so?
Yes, it is possible this way, with simple html markup:
<div class="image_box" data-cords="20,50,210,50,50,250,240,250">I am the text inside the div, I can be in several lines. It is important for text stay vertical and it is important the text to follow boundary box.</div>
Than do some script magic:
$.fn.skewText = function () {
return this.each(function (i) {
var thisText = $(this);
var coords = thisText.data('cords').split(',');
/* Calculate degree */
var deg = Math.tan((coords[5] - coords[1]) / (coords[4] - coords[0])) * 57.2957795;
/* Skew pixels for calculations */
var skewVal = coords[4] - coords[0];
/* Calculate position */
var cssWidth = (coords[2] - coords[0] - skewVal) + 'px';
var cssHeight = (coords[5] - coords[1]) + 'px';
var cssTop = coords[1] + 'px';
var cssLeft = (coords[0] * 1 + skewVal) + 'px'; /* Add a half of skew */
/* Wrapp and apply styles */
thisText.wrapInner('<div class="skew_padding" />').wrapInner('<div class="skew_text" />');
var skewText = thisText.find('.skew_text');
skewText.css({
'transform': 'skew(' + deg + 'deg)',
'top': cssTop,
'left': cssLeft,
'width': cssWidth,
'height': cssHeight,
'background': 'none rgba(0,0,0,.5)'
});
/* Now skew back each letter inside */
var skewPadding = skewText.find('.skew_padding');
var letters = skewPadding.text().split(' ');
var newText = '<span>' + letters.join('</span> <span>') + '</span>';
skewPadding.html(newText);
skewPadding.find('span').css({
'display': 'inline-block',
'transform': 'skew(' + (-deg) + 'deg)'
});
});
};
$('[data-cords]').skewText();
That is possible with this css:
.image_box {
position: relative;
width: 300px;
height: 300px;
background: yellow;
}
.skew_text {
position: absolute;
}
.skew_padding {
padding: 10px;
}

Categories