How do I remove the line connection between the ellipse? JS Canvas - javascript

So I am trying to draw a face with Javascript in a canvas and the smile is using ellipse(x, y, rX, rY, rot, start, end. I closed the path (closePath();) and that follow that with a stroke command (stroke();). This draws the ellipse, which looks like a half-circle. But this also draws a stroke which connects the two ends of the half-circle, which I don't want. It looks like this:
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
var w = 500;
var h = 300;
window.onload = function() {
c.style.backgroundColor = '#aaa';
c.width = w;
c.height = h;
c.tabIndex = '1';
c.style.outline = 'none';
c.style.display = 'block';
c.style.margin = '0 auto';
c.style.position = 'relative';
c.style.top = '50px';
document.body.style.margin = '0';
document.body.appendChild(c);
}
setInterval(function() {
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.ellipse(w / 2, h / 2, 30, 35, 0, 0, 2 * Math.PI);
ctx.closePath();
ctx.fillStyle = '#cf9454';
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.ellipse(w / 2 - 10, h / 2 - 10, 2, 2, 0, 0, 2 * Math.PI);
ctx.moveTo(w / 2 + 10, h / 2 - 10);
ctx.ellipse(w / 2 + 10, h / 2 - 10, 2, 2, 0, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = '#000';
ctx.fill();
ctx.beginPath();
ctx.ellipse(w / 2, h / 2 + 10, 16, 12, 0, 0, 1 * Math.PI);
ctx.closePath();
ctx.stroke();
}, 30);

You should simply omit the last closePath() call. Its intention is described in MDN's documentation:
The CanvasRenderingContext2D.closePath() method of the Canvas 2D API attempts to add a straight line from the current point to the start of the current sub-path.
It effectively adds that straight line to the "mouth" shape. So just leave that out:
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
var w = 500;
var h = 140; // reduced to make the smiley appear within the snippet area
window.onload = function() {
c.width = w;
c.height = h;
c.tabIndex = '1';
c.style.backgroundColor = '#aaa';
c.style.outline = 'none';
c.style.display = 'block';
c.style.margin = '0 auto';
c.style.position = 'relative';
c.style.top = '50px';
document.body.style.margin = '0';
document.body.appendChild(c);
}
setInterval(function() {
ctx.clearRect(0, 0, w, h);
ctx.beginPath();
ctx.ellipse(w / 2, h / 2, 30, 35, 0, 0, 2 * Math.PI);
ctx.closePath();
ctx.fillStyle = '#cf9454';
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.ellipse(w / 2 - 10, h / 2 - 10, 2, 2, 0, 0, 2 * Math.PI);
ctx.moveTo(w / 2 + 10, h / 2 - 10);
ctx.ellipse(w / 2 + 10, h / 2 - 10, 2, 2, 0, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fillStyle = '#000';
ctx.fill();
ctx.beginPath();
ctx.ellipse(w / 2, h / 2 + 10, 16, 12, 0, 0, 1 * Math.PI);
//ctx.closePath(); //<----- remove this
ctx.stroke();
}, 30);
Note that Unicode has characters for smileys. Maybe they are useful for your project? I would also move some of the styling to CSS definitions. The setInterval is currently useless; but I suppose you have it for future purposes.
For example:
var c = document.createElement('canvas');
var ctx = c.getContext('2d');
var w = 500;
var h = 140; // reduced to make the smiley appear within the snippet area
window.onload = function() {
c.width = w;
c.height = h;
c.tabIndex = 1;
document.body.appendChild(c);
ctx.font = "70px Verdana";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
setInterval(function() {
ctx.clearRect(0, 0, w, h);
ctx.fillText("🙂", w/2, h/2);
}, 30);
}
canvas {
background-color: #aaa;
outline: none;
display: block;
margin: 0 auto;
position: relative;
top: 50px;
}
body { margin: 0; }

Related

How to solve this canvas fillStyle problem?

class Entity {
constructor(name, type = 'player') {
this.name = name,
this.type = type
}
newObject(name, ...pvals) {
this[name] = {}
if (pvals) {
for (var i = 0; i < pvals.length; i += 2) {
this[name][pvals[i]] = pvals[i + 1]
}
}
}
}
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
canvas.height = window.innerHeight - 20
canvas.width = window.innerWidth
var frame = new Entity('frame', 'game-object')
var button = new Entity('button', 'player-component')
const radius = 70
var speed = 3
frame.newObject('$', 'r', radius)
button.newObject('$', 'r', radius / 3)
function updateFrame() {
ctx.fillStyle = 'black'
ctx.arc((canvas.width / 2), (canvas.height / 2), frame.$.r, 0, Math.PI * 2)
ctx.fill()
ctx.fillStyle = 'red'
ctx.arc((canvas.width / 2), (canvas.height / 2), button.$.r, 0, Math.PI * 2)
ctx.fill()
}
updateFrame()
<canvas></canvas>
As far as I know it should print big black circle in the middle of the canvas and on top of that a red small circle. But it just prints a big red circle. I just can't figure it out.
Just like #Teemu points out in the comment "Begin the paths" you must use the ctx.beginPath() between your arcs when you are changing colors
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath#examples
I simplified a lot of your code to show just the problem, you should do the same when you are troubleshooting class Entity was just a distraction and we can reproduce without it
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
ctx.beginPath()
ctx.fillStyle = 'black'
ctx.arc(50, 50, 20, 0, Math.PI * 2)
ctx.fill()
ctx.beginPath()
ctx.fillStyle = 'red'
ctx.arc(50, 50, 10, 0, Math.PI * 2)
ctx.fill()
<canvas></canvas>
You should add these 2 lines:
ctx.beginPath();
ctx.closePath();
function updateFrame() {
ctx.beginPath();
ctx.fillStyle = 'black'
ctx.arc((canvas.width / 2), (canvas.height / 2), frame.$.r, 0, Math.PI * 2)
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = 'red'
ctx.arc((canvas.width / 2), (canvas.height / 2), button.$.r, 0, Math.PI * 2)
ctx.closePath();
ctx.fill()
}

Circle is not connecting through lines properly using Canvas

I am trying to create 11 circles which connected through lines with a middle circle. I am trying to draw the circles. Here I have doing some r&d but I could not able to make lines. Please help me to complete this.
var canvas, ctx;
var circlePoints = [];
function createCanvasPainting() {
canvas = document.getElementById('myCanvas');
if (!canvas || !canvas.getContext) {
return false;
}
canvas.width = 600;
canvas.height = 600;
ctx = canvas.getContext('2d');
ctx.strokeStyle = '#B8D9FE';
ctx.fillStyle = '#B8D9FE';
ctx.translate(300, 250);
ctx.arc(0, 0, 50, 0, Math.PI * 2); //center circle
ctx.stroke();
ctx.fill();
var angleRotate = 0;
for (var i=0; i<11; i++) {
if (i > 0) {
angleRotate += 32.72;
}
lineToAngle(ctx, 0, 0, 200, angleRotate);
}
}
function lineToAngle(ctx, x1, y1, length, angle) {
angle *= Math.PI / 180;
var x2 = x1 + length * Math.cos(angle),
y2 = y1 + length * Math.sin(angle);
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.lineWidth = 1;
ctx.arc(x2, y2, 40, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();
circlePoints.push({x: x2, y: y2});
// console.log(circlePoints);
}
createCanvasPainting();
<canvas id="myCanvas"></canvas>
Here is my JSFiddle Link
See below I removed all the "noise" from your code.
Just circles with lines connecting with a middle circle.
canvas = document.getElementById('myCanvas');
canvas.width = canvas.height = 200;
ctx = canvas.getContext('2d');
ctx.lineWidth = 1;
ctx.translate(99, 99);
angle = 0;
function draw() {
ctx.clearRect(-99, -99, 200, 200);
ctx.beginPath();
ctx.arc(0, 0, 35 + Math.cos(angle / 3000), 0, Math.PI * 2);
ctx.stroke();
ctx.fill();
for (var i = 0; i < 11; i++) {
a = angle * Math.PI / 180;
x = 80 * Math.cos(a)
y = 80 * Math.sin(a)
ctx.beginPath();
ctx.arc(x, y, 18, 0, Math.PI * 2);
ctx.moveTo(x, y);
ctx.lineTo(0, 0);
ctx.fill();
ctx.stroke();
angle += 32.7;
}
}
setInterval(draw, 10);
<canvas id="myCanvas"></canvas>

Rotate HTML canvas circle scale

I am experiencing trouble in rotating a circle with HTML5 canvas.
the function is about control a circle,
but the scale is out of control...
anyone know how to adjust(or set rotate) the scale to fit the canvas circle?
The starting angle(0.7 pi) and endAngle(0.3 pi).
Do I need to reset the rotate?
--> ctx.rotate(Math.PI * 3 / 16);
-->(math.pi*15/10*1/8)
var degrees = 0;
var color = "lightblue";
var bgcolor = "#222";
var canvas, ctx, W, Htext;
function init_rpm(name, val) {
canvas = document.getElementById(name);
ctx = canvas.getContext("2d");
//dimensions
W = canvas.width;
H = canvas.height;
//Clear the canvas everytime a chart is drawn
ctx.clearRect(0, 0, W, H);
//Background 360 degree arc
ctx.beginPath();
ctx.lineWidth = 25;
ctx.strokeStyle = bgcolor;
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
ctx.stroke();
//center circle
ctx.save();
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
ctx.stroke();
ctx.restore();
// scale
ctx.save();
ctx.translate(300, 300);
for (var i = 0; i < 9; i++) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
ctx.moveTo(130, 0);
ctx.lineTo(140, 0);
ctx.stroke();
ctx.rotate(Math.PI * 3 / 16);
}
ctx.restore();
//angle in radians =angle in drgrees*pi/180 make color
var percent = val / 8000 * 100;
ctx.beginPath();
ctx.lineWidth = 30;
// ctx.strokeStyle= color;
var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
my_gradient.addColorStop(0, "#B31918");
my_gradient.addColorStop(1, "#FFA000");
ctx.strokeStyle = my_gradient;
//the arc start from the rightmost end. if we deduct 90 degrees from the angles
//the arc will start from the top most end
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
ctx.stroke();
//add text
ctx.fillStyle = color;
ctx.font = "7vh play";
// text=Math.floor(degrees/360*8)+' RPM';
text = degrees / 360 * 8;
text_width = ctx.measureText(text).width;
ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);
ctx.font = "3vh play";
text2 = 'RPM';
ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
}
function draw(val, name, type) {
// console.log(val);
if (name != "" || name != null) {
if (type == "rpm") {
if (val != "" || val != null) {
degrees = val / 1000 / 8 * 360;
} else {
degrees = 180;
}
init_rpm(name, val);
} else if (type == "kmh") {
if (val != "" || val != null) {
degrees = val;
} else {
degrees = 180;
}
init_kmh(name);
}
} else {
console.log('can not find canvas id');
}
}
$(document).ready(function () {
//canvas init
draw(0, "canvas3", "rpm");
var rpmControl2 = document.querySelector('input[id=get_rpm]');
rpmControl2.addEventListener('input', function () {
draw(this.value, "canvas3", "rpm");
});
});
#canvas2{
display:inline;
}
body{
background:#333;
font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
<input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
<span style="color:white">RPM</span>
<canvas id="canvas3" width="600" height="600"></canvas>
Your scale is drawn by drawing its lines in a single direction and then controlling the context's rotation to make all these lines point at a different angle.
Just like if you held a ruler always in the same direction and simply rotated the leaf of paper underneath.
So to control the rotation of your scale, you have to set the context's rotation (or leaf of paper) before you draw the first line.
var ctx = c.getContext('2d');
angle.oninput = function(e) {
ctx.clearRect(0, 0, c.width, c.height);
var rad = angle.value * (Math.PI / 180);
// move the context so its center be at 0,0
ctx.setTransform(1, 0, 0, 1, c.width/2, c.height/2);
// rotate it so we face the required angle
ctx.rotate(rad);
var stepAngle = Math.PI*2 / 14,
innerRad = c.width / 2.8,
outerRad = c.width / 2.5;
ctx.beginPath();
for(var i = 0; i < 12; i++) {
ctx.moveTo(0, innerRad); // move vertically
ctx.lineTo(0, outerRad); // draw line vertically
ctx.rotate(stepAngle); // rotate by fixed increment
}
ctx.stroke(); // all drawn, we can stroke
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset context's position
};
angle.oninput();
<input type="range" min="0" max="360" id="angle"><br>
<canvas id="c" width="200" height="200"></canvas>
And with your code:
var degrees = 0;
var color = "lightblue";
var bgcolor = "#222";
var canvas, ctx, W, Htext;
function init_rpm(name, val) {
canvas = document.getElementById(name);
ctx = canvas.getContext("2d");
//dimensions
W = canvas.width;
H = canvas.height;
//Clear the canvas everytime a chart is drawn
ctx.clearRect(0, 0, W, H);
//Background 360 degree arc
ctx.beginPath();
ctx.lineWidth = 25;
ctx.strokeStyle = bgcolor;
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.3 * Math.PI, false); //you can see thr src now
ctx.stroke();
//center circle
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(W / 2, H / 2, Math.floor(W / 3) - 40, 0.7 * Math.PI, 0.3 * Math.PI, false);
ctx.stroke();
//EDITS BEGIN HERE
// scale
ctx.setTransform(1, 0, 0, 1, 300, 300);
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
// there should be 10 lines
var stepAngle = (Math.PI * 2) / 10;
// begin angle
ctx.rotate(0.7 * Math.PI);
// draw only 9 of the 10 lines
for (var i = 0; i < 9; i++) {
ctx.moveTo(130, 0);
ctx.lineTo(140, 0);
ctx.rotate(stepAngle);
}
ctx.stroke();
ctx.setTransform(1, 0, 0, 1, 0, 0);
//EDITS END HERE
var percent = val / 8000 * 100;
ctx.beginPath();
ctx.lineWidth = 30;
var my_gradient = ctx.createLinearGradient(0, 150, 250, 300);
my_gradient.addColorStop(0, "#B31918");
my_gradient.addColorStop(1, "#FFA000");
ctx.strokeStyle = my_gradient;
//the arc start from the rightmost end. if we deduct 90 degrees from the angles
//the arc will start from the top most end
ctx.arc(W / 2, H / 2, Math.floor(W / 3), 0.7 * Math.PI, 0.7 * Math.PI + 1.6 * Math.PI / 100 * percent, false); //you can see thr src now
ctx.stroke();
//add text
ctx.fillStyle = color;
ctx.font = "7vh play";
// text=Math.floor(degrees/360*8)+' RPM';
text = degrees / 360 * 8;
text_width = ctx.measureText(text).width;
ctx.fillText(text, W / 2 - text_width / 2, H / 2 + 15);
ctx.font = "3vh play";
text2 = 'RPM';
ctx.fillText(text2, W / 2 - text_width / 2, H / 2 + 70);
}
function draw(val, name, type) {
// console.log(val);
if (name != "" || name != null) {
if (type == "rpm") {
if (val != "" || val != null) {
degrees = val / 1000 / 8 * 360;
} else {
degrees = 180;
}
init_rpm(name, val);
} else if (type == "kmh") {
if (val != "" || val != null) {
degrees = val;
} else {
degrees = 180;
}
init_kmh(name);
}
} else {
console.log('can not find canvas id');
}
}
$(document).ready(function () {
//canvas init
draw(0, "canvas3", "rpm");
var rpmControl2 = document.querySelector('input[id=get_rpm]');
rpmControl2.addEventListener('input', function () {
draw(this.value, "canvas3", "rpm");
});
});
#canvas2{
display:inline;
}
body{
background:#333;
font-family: 'Play', sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div class="container-fluid">
<input id="get_rpm" type="number" value="0" min="0" max="8000" step="100" />
<span style="color:white">RPM</span>
<canvas id="canvas3" width="600" height="600"></canvas>

manipulate text with html5 canvas

Hello I want to draw the logo of Chelsea Football Club and I have got already the 'big things'
like the circle and the innerwhite space etc.. and the text but there is where I got a problem with.. in the logo the text is like in a halve circle shape but I can't find a way to draw it like this in canvas for an example for the right text see image below and see also my code
$(function () {
//variables
var canvas = document.getElementById("chelseaLogo");
var CanvasContext = canvas.getContext("2d");
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 170;
var radiusWhite = radius - 30;
// outside logo
CanvasContext.beginPath();
CanvasContext.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
CanvasContext.fillStyle = '#0B49DB';
CanvasContext.fill();
//stroke
CanvasContext.lineWidth = 2;
CanvasContext.strokeStyle = '#FFF700';
CanvasContext.stroke();
//white innercircle
CanvasContext.beginPath();
CanvasContext.arc(centerX, centerY, radiusWhite, 0, 2 * Math.PI, false);
CanvasContext.fillStyle = '#fff';
CanvasContext.fill();
//text top
CanvasContext.font = '15pt Calibri';
CanvasContext.fillText('Chelsea', 155, 25);
//text bottom
CanvasContext.font = '15pt Calibri';
CanvasContext.fillText('Football Club', 140, 330);
});
I've modified the tutorial code that #Esailija posted to be a bit more accurate/flexible:
function drawTextAlongArc(context, str, hei, centerX, centerY, radius, angle, above) {
var met, wid;
context.save();
context.translate(centerX, centerY);
if (!above) {
radius = -radius;
angle = -angle;
}
else{
hei = 0;
}
context.rotate(-1 * angle / 2);
context.rotate(-1 * (angle / str.length) / 2);
for (var n = 0; n < str.length; n++) {
var char = str[n];
met = context.measureText(char);
wid = met.width;
console.log(met);
context.rotate(angle / str.length);
context.fillText(char, -wid / 2, -radius + hei);
context.strokeText(char, -wid / 2, -radius + hei);
}
context.restore();
}
ctx.font = 'bold 40pt impact';
ctx.fillStyle = '#000';
ctx.strokeStyle = '#f00';
ctx.lineWidth = 2;
drawTextAlongArc(ctx, "CHELSEA", 40, 200, 200, 100, Math.PI*3/5, true);
ctx.font = 'bold 20pt impact';
drawTextAlongArc(ctx, "FOOTBALL CLUB", 30, 200, 200, 100, Math.PI*3/5, false);
ctx.beginPath();
ctx.arc(200,200,100,0,Math.PI*2,false);
ctx.stroke();
You can see an example of this here: http://jsfiddle.net/6uQSS/1/

Set attributes of HTML canvas arc

I'm still new to HTML5 and canvas. I'm setting points on a canvas as such:
var ctx = canvas.getContext("2d");
for (var i = 0; i < 500; i++) {
ctx.fillStyle = 'rgba(255,255,255,0.2)';
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true);
ctx.fill();
}
Is there a way such that once the canvas is drawn, when I look for say, "200", I can identify the particular dot and change its color? Or would it be better to redraw the entire canvas?
var canvas, ctx, points;
var radius = 10;
var num = 20;
$(function () {
points = [];
for (var i = 0; i < num; i++) {
points.push({
x: Math.random() * 300 >> 0,
y: Math.random() * 200 >> 0
});
}
canvas = document.getElementById('canvas');
ctx = canvas.getContext("2d");
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, 300, 200);
for (var i in points) {
ctx.fillStyle = 'rgba(255,255,255,0.8)';
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true);
ctx.fill();
}
});
var initrand = Math.random() * num >> 0;
function change() {
var random = initrand;
ctx.fillStyle = '#234263';
ctx.beginPath();
ctx.arc(points[random].x, points[random].y, radius, 0, Math.PI * 2, true);
ctx.fill();
initrand = Math.random() * num >> 0;
}
Demo for above Code

Categories

Resources