how to minimize a flowchart - javascript

I have managed to make some flow charts (vertical chart and pie chart) but I have a problem,I want to minimize the charts because are occupying almost my entire page.
Here is what I have done:
<form action="listacumparaturi" method="get">
<canvas width="2200" height="2200" id="myCanvas"></canvas>
<script>
var x = "${sumC}";
var y = "${sumG}";
var z = "${sumP}";
var w = "${sumCa}";
total = "${sumT}";
var vertical = {
Calorii: x,
Grasimi: y,
Proteine: z,
Carbohidrati: w
};
var data = Object.keys(vertical);
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
total = "${sumT}";
color = ['orange', 'red', 'blue', 'green', 'black'];
start = 0;
for (var i = 0; i < data.length; i++) {
ctx.fillStyle = color[i];
ctx.fillRect((i * 60) + 50, x, 10, -(vertical[data[i]]));
ctx.font = "13px Arial";
ctx.fillText(data[i], (i * 60) + 51, x * 1.015);
ctx.fillText((1 * i), 20, ((32 * -i) + 920));
ctx.beginPath();
ctx.moveTo(600, 150);
ctx.arc(600, 150, 150, start, start +
(Math.PI * 2 * (vertical[data[i]] / total)), false);
ctx.lineTo(600, 150);
ctx.fillStyle = color[i];
ctx.fill();
start += Math.PI * 2 * (vertical[data[i]] / total);
}
</script>
</form>
Does anyone know how can I minimize this flow charts?I want the values to be the same but the pictures be minimized.
Here you can find a preview: http://codepen.io/nagasai/pen/Meayrb
Thanks!

I just updated the scale in the code pen URL ..Added total while calculating vertical bar height -http://codepen.io/nagasai/pen/Meayrb
ctx.fillRect((i * 60) + 50, 300, 10,( -(vertical[data[i]])*100)/total);
ctx.font = "9px Arial";
ctx.fillText(data[i], (i * 60) + 51, 742);
ctx.fillText((700 * i), 30, (((70) * -i) + 300));
And scale on y-axxis and bar height are dynamic now and adjust automatically based on your inputs.
Hope this is helpful for you

Related

Identify points in each quadrant of a canvas

How do you divide a canvas into four quadrants (top-left, bottom-left, top-right, bottom-right) and then identify points drawn at random in each quadrant?
Here is my not so futile attempt:
var myCanvas = document.getElementById("showCanvas");
var myContext = myCanvas.getContext("2d");
var xAxis = [];
var yAxis = [];
for (var i = 0; i < 4; i++) {
var x = Math.floor(Math.random() * 600);
var y = Math.floor(Math.random() * 350);
var r = 5;
xAxis.push(x);
yAxis.push(y);
myContext.arc(x, y, r, 0, 2 * Math.PI, true);
myContext.closePath();
myContext.fill();
}
var startingPoint = xAxis[0] + ", " + yAxis[0];
var endingPoint = xAxis[3] + ", " + yAxis[3];
var horizontalSlash = myCanvas.width / 2;
var verticalSlash = myCanvas.height / 2;
var remainder = horizontalSlash % verticalSlash;
<canvas id="showCanvas"></canvas>
And the result should show up in these tags:
<h3>The starting point of the line is: <label id="sumPoints">e.g. top, right</label></h3>
<h3>The end point of the line is: <label id="sumPoints">e.g. bottom, left</label></h3>
The suggestion to check the point's coordinates is correct...
Here is an example using a bit of math.
const canvas = document.getElementById("showCanvas");
const ctx = canvas.getContext("2d");
const names = [
["top left", "bottom left"],
["top right", "bottom right"]
]
var points = []
for (var i = 0; i < 4; i++) {
var x = Math.random() * canvas.width
var y = Math.random() * canvas.height
var quadrant = names[Math.floor(x / (canvas.width / 2))][Math.floor(y / (canvas.height / 2))]
points.push({ x, y, quadrant })
ctx.arc(x, y, 5, 0, 2 * Math.PI);
ctx.fillText(quadrant, x-8, y-8)
ctx.closePath();
ctx.fill();
}
console.log(points[0])
canvas {
border:2px dotted gray;
}
<canvas id="showCanvas" width=200 height=200></canvas>

Placing a letter randomly in a canvas offset by a % from border

I have this canvas where I place a letter randomly within the canvas.
var w = Math.random() * canvas.width;
var h = Math.random() * canvas.height;
drawRandomCircle(canvas,w,h);
function drawRandomCircle(canvas,w,h)
{
var fontSize = '35';
var ctx = canvas.getContext("2d");
var color = 'rgba(245, 66, 66,1.0)';
ctx.fillStyle = color;
ctx.font = fontSize + 'pt Arial';
ctx.fillText('O', w, h);
}
The results:
I would like to improve further on the function to include an offset in % from the canvas boundary to limit where the letter will appear.
The results would be similar to something similar to this.
Any ideas?
You need to take into account the 10% on the borders.
Try the following which uses this principle... but also remember that the co-ordinates for the canvas are top-left based... but when you do the font it will go UP (not down) so you have to take that into account as well.
var canvas = document.getElementsByTagName("canvas")[0];
var fontSizePx = 35;
// Get 10% of the width/height
var cw = (canvas.width / 10);
var ch = (canvas.height / 10);
// Get 80% of the width/height but minus the size of the font
var cw80 = (cw * 8) - fontSizePx;
var ch80 = (ch * 8) - fontSizePx;
for(var i = 0; i < 10; i++) {
// Get random value within center 80%
var w = (Math.random() * cw80) + cw;
// Add on the size of the font to move it down
var h = (Math.random() * ch80) + ch + fontSizePx;
drawRandomCircle(canvas,w,h);
}
function drawRandomCircle(canvas,w,h) {
var ctx = canvas.getContext("2d");
var color = 'rgba(245, 66, 66,1.0)';
ctx.fillStyle = color;
ctx.font = fontSizePx.toString() + 'px Arial';
ctx.fillText('O', w, h);
}
canvas {
border:1px solid black;
}
<canvas></canvas>

How to generate random non-overlapping polygons without free spaces

I need to generate random non-overlapping polygons without free spaces (. They can have any shape.
The only thing I found is an example that uses p5.js to create only non-overlapping circles, but free spaces are present.
Does anyone know how to do it?
// Uses P5.js for canvas creation and drawing
function setup() {
var circles = [],
circle = {},
overlapping = false,
NumCircles = 4000,
protection = 1000,
counter = 0,
canvasWidth = window.innerWidth,
canvasHeight = window.innerHeight;
createCanvas(canvasWidth, canvasHeight);
// populate circles array
// brute force method continues until # of circles target is reached
// or until the protection value is reached
while (circles.length < NumCircles &&
counter < protection) {
circle = {
x: random(width),
y: random(height),
r: random(3, 36)
};
overlapping = false;
// check that it is not overlapping with any existing circle
// another brute force approach
for (var i = 0; i < circles.length; i++) {
var existing = circles[i];
var d = dist(circle.x, circle.y, existing.x, existing.y)
if (d < circle.r + existing.r) {
// They are overlapping
overlapping = true;
// do not add to array
break;
}
}
// add valid circles to array
if (!overlapping) {
circles.push(circle);
}
counter++;
}
// circles array is complete
// draw canvas once
background("#233")
fill("#2AC1A6");
noStroke();
for (var i = 0; i < circles.length; i++) {
ellipse(circles[i].x, circles[i].y,
circles[i].r*2, circles[i].r*2);
}
}
* {
padding: 0;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
Your question is not very specific...
random non-overlapping polygons without free spaces
Rectangles are polygons, let's make a bunch of those with random sizes and colors
Here is a starting point:
canvas = document.getElementById('c');
ctx = canvas.getContext('2d');
var colors = ["red", "blue", "orange", "green", "yellow"]
h = Math.floor(canvas.height / Math.floor(Math.random() * 15 + 4))
for (y = 0; y < canvas.height; y += h) {
w = Math.floor(canvas.width / Math.floor(Math.random() * 15 + 4))
for (x = 0; x < canvas.width; x += w) {
c = colors[Math.floor(Math.random() * 10) % 5]
draw(x, y, w, h, c)
}
}
function draw(x, y, w, h, color) {
ctx.beginPath();
ctx.rect(x, y, w, h)
ctx.stroke();
ctx.fillStyle = color
ctx.fill();
}
<canvas id="c"></canvas>
Here is a function to help you draw "random" polygons:
var ctx = document.getElementById('c').getContext('2d');
function polygon(sides, size, Xcenter, Ycenter, offset) {
ctx.beginPath();
ctx.moveTo(Xcenter + size * Math.cos(offset), Ycenter + size * Math.sin(offset));
for (var i = 1; i <= sides; i += 1) {
x = Xcenter + size * Math.cos(i * 2 * Math.PI / sides +offset)
y = Ycenter + size * Math.sin(i * 2 * Math.PI / sides +offset)
ctx.lineTo(x, y);
}
ctx.stroke();
}
arr = [3, 4, 5, 6, 7];
arr.sort(() => Math.random() - 0.5);
for (var i = 1; i <= 5; i += 1) {
offset = Math.random() * 5
polygon(arr[i-1], 40, 85*i, 60, offset)
}
<canvas id="c" width=600></canvas>

HTML 5 fortune wheel (lunchwheel)

I have been working on a simple fortune wheel implementation form here, using HTML 5 , but I'm having some issue in finding the winner segment , here is the code in JSFiddle :
http://jsfiddle.net/bramp/94jP6/
Important functions in JSFiddle :
// Called when segments have changed
update: function() {
// Ensure we start mid way on a item
//var r = Math.floor(Math.random() * wheel.segments.length);
var r = 0;
wheel.angleCurrent = ((r + 0.5) / wheel.segments.length) * Math.PI * 2;
var segments = wheel.segments;
var len = segments.length;
var colors = wheel.colors;
var colorLen = colors.length;
// Generate a color cache (so we have consistant coloring)
var seg_color = new Array();
for (var i = 0; i < len; i++)
seg_color.push(colors[segments[i].hashCode().mod(colorLen)]);
wheel.seg_color = seg_color;
wheel.draw();
}
and
drawNeedle: function() {
var ctx = wheel.canvasContext;
var centerX = wheel.centerX;
var centerY = wheel.centerY;
var size = wheel.size;
ctx.lineWidth = 1;
ctx.strokeStyle = '#000000';
ctx.fileStyle = '#ffffff';
ctx.beginPath();
ctx.moveTo(centerX + size - 40, centerY);
ctx.lineTo(centerX + size + 20, centerY - 10);
ctx.lineTo(centerX + size + 20, centerY + 10);
ctx.closePath();
ctx.stroke();
ctx.fill();
// Which segment is being pointed to?
var i = wheel.segments.length - Math.floor((wheel.angleCurrent / (Math.PI * 2)) * wheel.segments.length) - 1;
// Now draw the winning name
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillStyle = '#000000';
ctx.font = "2em Arial";
ctx.fillText(wheel.segments[i], centerX + size + 25, centerY);
},
in line 256 is where the current code is getting the winner :
var i = wheel.segments.length - Math.floor((wheel.angleCurrent / (Math.PI * 2)) * wheel.segments.length) - 1;
but thats on the right side of the wheel , Im trying to make it get the segment on top as the winner point . I have been struggling with it for a long time and i appreciate your help or guidance. Thanks
Here is a working solution Fiddle . And the explanation is below:
First we need to draw the pointer to the correct position, on top of the wheel:
drawNeedle: function() {
...
ctx.beginPath();
ctx.moveTo(centerX + 20, centerY - size - 20);
ctx.lineTo(centerX - 20, centerY - size - 20);
ctx.lineTo(centerX , centerY - size + 20);
ctx.closePath();
...
}
In the code segment here that you have given:
var i = wheel.segments.length - Math.floor((wheel.angleCurrent / (Math.PI * 2)) * wheel.segments.length) - 1;
The wheel.angleCurrent / (Math.PI * 2) part means that it is on the right side. Note that in JavaScript that is where we start for a "unit circle". To fix this we just need to off-set the angle by 90 degrees (or in our case add Math.PI/2 in radians):
var change = wheel.angleCurrent + (Math.PI/2);
var i = wheel.segments.length - Math.floor((change / ( Math.PI * 2)) * wheel.segments.length) - 1;
if(i < 0) i = i + 17; // 17 = wheel.segments.length
The way i is calculated is depended on that we start on the right. It offsets by a few items when we change it going from -5 to 12 other than 0 to 16. To fix that on negative items (our offset items) we just need to add them be our 13 to 16. In other-words add 17 (which is the same as wheel.segments.length).

If/Then Javascript to Display HTML Code

I have some html5 and javascript code to create a spinning roulette wheel. It is split up into 14 outcomes. My question is, how can I get some unique HTML code to display per each outcome of the wheel. For example, if the wheel lands on Business, some text will appear below the wheel that has information on Business.
Here is my HTML code and below it is a link to a working example:
<!--[if IE]><script type="text/javascript" src="/sites/default/files/1010/source/excanvas.js"></script><![endif]-->
<input type="button" value="spin" onclick="spin();" style="float: left;" />
<canvas id="wheelcanvas" width="800" height="750"></canvas>
<script type="application/javascript">
var colors = ["#B8D430", "#3AB745", "#029990", "#3501CB",
"#2E2C75", "#673A7E", "#CC0071", "#F80120",
"#F35B20", "#FB9A00", "#FFCC00", "#FEF200", "#B2DF00", "#5C8300"];
var classes = ["Business", "Office Education", "Continuing Care Assistant", "Practical Nursing",
"Primary Care Paramedic", "Early Childhood Education", "Cooking", "Electrician",
"Heavy Equipment Operator", "Industrial Mechanic - Millwright", "Plumbing & Pipefitting", "Truck Driver Training", "Welding", "Power Engineering"];
var startAngle = 0;
var arc = Math.PI / 7;
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var ctx;
function draw() {
drawRouletteWheel();
}
function drawRouletteWheel() {
var canvas = document.getElementById("wheelcanvas");
if (canvas.getContext) {
var outsideRadius = 300;
var textRadius = 260;
var insideRadius = 100;
ctx = canvas.getContext("2d");
ctx.clearRect(5,0,1000,1000);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.font = 'bold 10px sans-serif';
for(var i = 0; i < 14; i++) {
var angle = startAngle + i * arc;
ctx.fillStyle = colors[i];
ctx.beginPath();
ctx.arc(400, 400, outsideRadius, angle, angle + arc, false);
ctx.arc(400, 400, insideRadius, angle + arc, angle, true);
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "black";
ctx.translate(400 + Math.cos(angle + arc / 2) * textRadius, 400 + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var text = classes[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
ctx.restore();
}
//Arrow
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(400 - 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 0, 400 - (outsideRadius - 13));
ctx.lineTo(400 - 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius + 5));
ctx.fill();
}
}
function spin() {
spinAngleStart = Math.random() * 10 + 10;
spinTime = 0;
spinTimeTotal = Math.random() * 3 + 4 * 1000;
rotateWheel();
}
function rotateWheel() {
spinTime += 30;
if(spinTime >= spinTimeTotal) {
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawRouletteWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel() {
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
ctx.save();
ctx.font = 'bold 30px sans-serif';
var text = classes[index]
ctx.fillText(text, 400 - ctx.measureText(text).width / 2, 400 + 10);
ctx.restore();
document.getElementById('wheelResult').innerHTML = 'Test' + text;
}
function easeOut(t, b, c, d) {
var ts = (t/=d)*t;
var tc = ts*t;
return b+c*(tc + -3*ts + 3*t);
}
draw();
</script>
<p id="wheelResult"></p>
http://www.ctrc.sk.ca/wheel.html
There are a couple of ways to do it but this is the way I would do it.
You could create a div tag with the css style of display:none and then set it with the info desired and hide and show it as needed.
Example:
<script>
var htmlData = ['<h1>Business</h1><br><span>What is Business?</span><br>...', ...];
....
function spin()
{
//Hide description box.
document.getElementById('idDescriptionBox').style.display = 'none';
spinAngleStart = Math.random() * 10 + 10;
....
}
....
function stopRotateWheel()
{
....
//Set description and display it.
var descriptionBox = document.getElementById('idDescriptionBox');
descriptionBox.innerHTML = htmlData[index];
descriptionBox.style.display = 'block';
}
....
</script>
<div id="idDescriptionBox" style="display:none;">
<!--Description info in here-->
....
</div>

Categories

Resources