I'm currently working on a HTML5 Canvas project (I wrote a separate question about it here). I think one of the solutions to the problems I am facing would be to create a reference for the path (saved as an object), and use the method ispointinpath to check if my mouse position is within the path or not – if its not, it resets the game.
I took a stab at creating a constructor function for a complex path shape. Here's what the complex shape looks like as raw code:
var canvas = document.querySelector('canvas');
// returning a drawing context to a variable 'c'
// allows you to draw 2d elements
var c = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 700;
canvas.style.width = 1000;
canvas.style.height = 700;
c.beginPath();
c.moveTo(350, 650); //start
c.lineTo(350, 200);
c.lineTo(900, 200);
c.lineTo(900, 250);
c.lineTo(700, 250);
c.lineTo(600, 250);
c.lineTo(600, 650);
c.fillStyle = "#C1EEFF";
c.fill();
<canvas></canvas>
Here's what it looks like as a constructor function that I tried to make:
var canvas = document.querySelector('canvas');
// returning a drawing context to a variable 'c'
// allows you to draw 2d elements
var c = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 700;
canvas.style.width = 1000;
canvas.style.height = 700;
var points = [(350, 200), (900, 200), (900, 250), (700, 250), (600, 250), (600, 650)];
function Path(startX, startY, array, color){
c.beginPath();
c.moveTo(startX, startY);
// For however many element pairs in the array, create a lineTo statement
for(i = 1; i < array.length; i++){
c.lineTo(array[i][0], array[i][1]);
}
c.fillStyle = color;
c.fill();
}
var blue = new Path(350, 200, points, '#C1EEFF');
<canvas></canvas>
It doesn't seem to be working. Does anyone know why that is? Also, what would be the best syntax for what I'm trying to do?
It would be better if you use an object with position x, y
var canvas = document.querySelector("canvas");
// returning a drawing context to a variable 'c'
// allows you to draw 2d elements
var c = canvas.getContext("2d");
canvas.width = 1000;
canvas.height = 700;
canvas.style.width = 1000;
canvas.style.height = 700;
var points = [
{ x: 350, y: 200 },
{ x: 900, y: 200 },
{ x: 900, y: 250 },
{ x: 700, y: 250 },
{ x: 600, y: 250 },
{ x: 600, y: 650 }
];
function Path(startX, startY, array, color) {
c.beginPath();
c.moveTo(startX, startY);
// For however many element pairs in the array, create a lineTo statement
for (var i = 1; i < array.length; i++) {
c.lineTo(array[i].x, array[i].y);
}
c.fillStyle = color;
c.fill();
}
var blue = new Path(350, 200, points, "#C1EEFF");
<canvas></canvas>
First issue is your points array:
var points = [(350, 200), (900, 200),...
that is not a correct bi-dimensional array, maybe you meant:
var points = [[350, 200], [900, 200],...
also in your code Path is a function not a class, not sure why you doing new Path(...)
maybe you got that mixed with new Path2D() but that is completely different...
Look at the parameters for isPointInPath:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath#syntax
Here is a working example
var canvas = document.querySelector('canvas');
var c = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 700;
// Function to generate a Path2D object
function Path(array) {
let path = new Path2D();
path.moveTo(array[0][0], array[0][1]);
for (i = 1; i < array.length; i++) {
path.lineTo(array[i][0], array[i][1]);
}
path.lineTo(array[0][0], array[0][1]);
return path
}
//Create the paths
var big = [[350,200], [900,200], [900,250], [700,250], [600,250], [600,650], [350,650]];
var blue = Path(big);
var triangle = [[25,10], [70,10], [90,85]];
var red = Path(triangle);
// Draw all the paths
c.beginPath()
c.fillStyle = "blue";
c.fill(blue);
c.beginPath()
c.fillStyle = "red";
c.fill(red);
// use isPointInPath
console.log(c.isPointInPath(blue, 10, 10))
console.log(c.isPointInPath(blue, 351,201))
<canvas></canvas>
Now on the now closed question my suggestion to using isPointInPath is to improve scalability, you had a bunch of hard coded if statement, that approach for more complex polygons just would not do... BUT you still have the problem in your game how to handle the transition between levels, that was the root problem on that question.
You seem to be trying to access your array coordinates using this syntax array[i][0], array[i][1] however your array is NOT an array of arrays it is an array of parenthesis. I don’t have time to play with it but try making it an array of arrays so you can then access element [0] and [1].
[[350, 200], [400, 250]] etc
EDIT:
I am providing an ES6 class to create your maps. This is just another option on top of the others provided here.
const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 700;
let points = [[300, 400], [400, 400], [400, 350], [400, 250], [700, 250], [700, 150], [750, 150], [750, 50], [775, 50], [775, 175], [725, 175], [725, 400], [500, 400], [500, 500], [500, 650], [300, 650] ];
let points2 = [[750, 50], [775, 50], [775, 100], [750, 100]];
class Map {
constructor(start_x, start_y, arr, c) {
this.start_x = start_x;
this.start_y = start_y;
this.arr = arr;
this.color = c;
}
draw() {
c.beginPath();
c.moveTo(this.start_x, this.start_y); //start
this.arr.forEach(point => c.lineTo(point[0], point[1]));
c.fillStyle = this.color;
c.fill();
c.closePath();
}
}
let map1 = new Map(300, 650, points, 'blue');
let map1Finish = new Map(750, 100, points2, 'red');
map1.draw();
map1Finish.draw();
Related
I would like to draw this image on canvas without the transparent parts. The principle of my rendering is that I crop small images from a large image using the createImageBitmap method and store them in an array. I then render them on the canvas one by one. The problem is that it also unnecessarily draws the transparent parts. So if I log my array I get this. Since my map is 10x10 tiles it results in 100 images (of which 96 are useless). Instead, I would like to save only 4 images.
Not only that it messes up my performance but I have more reasons why it bothers me. Is there a way to solve this problem?
My code so far:
(async () => {
const img = new Image();
img.src = "./img/obstacles.png";
await img.decode();
let tiles = [];
let tileWidth = 32;
let tileHeight = 32;
for (let i = 0; i < 100; i++) {
let x = i % 10;
let y = Math.floor(i / 10);
let bmp = await createImageBitmap(img, x * tileWidth, y * tileHeight, tileWidth, tileHeight); // index.js:13
tiles.push({
bmp,
x,
y
})
}
console.log(tiles)
const canvas = document.querySelector("canvas");
canvas.width = 320;
canvas.height = 320;
const ctx = canvas.getContext("2d");
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
tiles.forEach((tile) => {
ctx.drawImage(tile.bmp, tile.x * tileWidth, tile.y * tileHeight);
})
// requestAnimationFrame(draw)
}
draw();
})();
The best is to prepare your asset correctly, so here that would mean having only the 3 unique sprites in your atlas:
Then you can use your simple loop to get these as separate objects.
However it's not uncommon to have sprites of different sizes in the same atlas, in such a case, your simple loop won't do. Instead, you should prepare a coordinates dictionary (e.g as a JSON file, or embedded directly in your js), with all the coordinates of each sprites.
Most spritesheet generating tools will produce this for you.
Here is an example where I just added one big sprite to the atlas:
(async () => {
// If you are same-origin, it's better to fetch as a Blob
// and create your ImageBitmap from the Blob
// Here we aren't, so we have to go through an <img>
const img = new Image();
img.src = "https://i.stack.imgur.com/h7w1C.png";
await img.decode();
document.body.append(img);
// We hardcode the coords of each sprite
const map = [
// [x, y, w, h]
[0, 0, 32, 32],
[0, 32, 32, 32],
[0, 64, 32, 32],
[32, 0, 96, 96],
];
const tiles = [];
for (const [x, y, w, h] of map) {
const bmp = await createImageBitmap(img, x, y, w, h);
tiles.push({
bmp,
x,
y
})
}
console.log(tiles)
const canvas = document.querySelector("canvas");
canvas.width = 320;
canvas.height = 320;
const ctx = canvas.getContext("2d");
let m = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
m = (m + 0.005) % 0.5;
const margin = m + 1;
tiles.forEach((tile) => {
// we add some margin to show these are separate bitmaps
ctx.drawImage(tile.bmp, tile.x * margin, tile.y * margin);
})
requestAnimationFrame(draw)
}
draw();
})().catch(console.error);
.as-console-wrapper { max-height: 100px !important }
<canvas></canvas>
I'am working on simulation of train station control panel. I created canvas with map of station and interactive elements. I decided to create class with signals for trains to save lines of code. It looks like this:
class enterSignal{
constructor(status, position, x, y, canvas){ //status and position are not used yet
this.ctx1 = canvas.getContext('2d');
this.ctx1.beginPath();
this.ctx1.arc(x, y, 5, 0, 2 * Math.PI);
this.ctx1.fillStyle = "rgb(109, 109, 109)";
this.ctx1.fill();
}
goAhead(){
this.ctx1.fillStyle = 'green';
this.ctx1.fill();
}
}
The goAhead() method changes color of ctx1 canvas to green (go ahead signal for train driver). The main problem is when I create two objects of enterSignal class and run goAhead() method for single object it works only for last object. For example:
var enterSignal1 = new enterSignal("red", "left", 50, 190, canvas);
var enterSignal2 = new enterSignal("red", "right", 930, 150, canvas);
enterSignal1.goAhead();
It affects on enterSignal2 instead of enterSignal1. So where is the problem?
Here is another way...
just like they mentioned in the comments, we re-draw the element.
class enterSignal {
constructor(color, x, y, canvas) {
this.ctx1 = canvas.getContext('2d');
this.x = x
this.y = y
this.draw(color)
}
draw(color) {
this.ctx1.beginPath();
this.ctx1.arc(this.x, this.y, 8, 0, 2 * Math.PI);
this.ctx1.fillStyle = color;
this.ctx1.fill();
}
}
const canvas = document.getElementById("c");
var enterSignal1 = new enterSignal("red", 10, 10, canvas);
var enterSignal2 = new enterSignal("red", 20, 30, canvas);
var enterSignal3 = new enterSignal("red", 30, 50, canvas);
enterSignal1.draw("green");
enterSignal2.draw("yellow");
<canvas id="c"></canvas>
I need to apply several matrix transformations before drawing a shape, however (if on somewhere) I use rotate() the coordinates are inverted and/or reversed and cannot continue without knowing if the matrix was previously rotated.
How can solve this problem?
Example:
<canvas width="300" height="300"></canvas>
<script>
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "silver";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(0, canvas.height/2);
ctx.lineTo(canvas.width, canvas.height/2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(canvas.width/2, 0);
ctx.lineTo(canvas.width/2, canvas.height);
ctx.stroke();
ctx.translate(150, 150);
ctx.rotate(-90 * 0.017453292519943295);
ctx.translate(-150, -150);
// move the red rectangle 100px to the left (top-left)
// but instead is moved on y axis (right-bottom)
ctx.translate(-100, 0);
// more matrix transformations
// ....
// ....
// now finally draw the shape
ctx.fillStyle = "red";
ctx.fillRect(150, 150, 100, 50);
</script>
Can be this Translation after rotation the solution?
It looks like you aren't resetting the canvas matrix each time you make a new transformation.
The Canvas API has the save() and restore() methods. Canvas states are stored on a stack. Every time the save() method is called, the current drawing state is pushed onto the stack. A drawing state consists of transformations that have been applied along with the attributes of things like the fillStyle. When you call restore(), the previous settings are restored.
// ...
ctx.save(); // save the current canvas state
ctx.translate(150, 150);
ctx.rotate(-90 * 0.017453292519943295);
ctx.translate(-150, -150);
ctx.restore(); // restore the last saved state
// now the rectangle should move the correct direction
ctx.translate(-100, 0);
Check out this link for more information on the save and restore methods.
OK finally, i solved the problem by rotating the translation point before applying it. This function does the trick:
function helperRotatePoint(point, angle) {
let s = Math.sin(angle);
let c = Math.cos(angle);
return { x: point.x * c - point.y * s, y: point.x * s + point.y * c};
}
rotating the translation point using the inverted angle I obtain the corrected translation
helperRotatePoint(translation_point, -rotation_angle);
working code:
let canvas = document.querySelector("canvas");
// proper size on HiDPI displays
canvas.style.width = canvas.width;
canvas.style.height = canvas.height;
canvas.width = Math.floor(canvas.width * window.devicePixelRatio);
canvas.height = Math.floor(canvas.height * window.devicePixelRatio);
let ctx = canvas.getContext("2d");
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
ctx.fillStyle = "whitesmoke";
ctx.fillRect(0, 0, canvas.width, canvas.height);
class UIElement {
constructor(x, y, width, height, color) {
// PoC
this.draw_pos = {x, y};
this.draw_size = {width, height};
this.color = color;
this.rotate = 0;
this.scale = {x: 1, y: 1};
this.translate = {x: 0, y: 0};
this.skew = {x: 0, y: 0};
this.childs = [];
}
addChild(uielement) {
this.childs.push(uielement);
}
helperRotatePoint(point, angle) {
let s = Math.sin(angle);
let c = Math.cos(angle);
return {
x: point.x * c - point.y * s,
y: point.x * s + point.y * c
};
}
draw(cnvs_ctx, parent_x, parent_y) {
// backup current state
cnvs_ctx.save();
let elements_drawn = 1;// "this" UIElement
// step 1: calc absolute coordinates
let absolute_x = parent_x + this.draw_pos.x;
let absolute_y = parent_y + this.draw_pos.y;
// step 2: apply all transforms
if (this.rotate != 0) {
cnvs_ctx.translate(absolute_x, absolute_y)
cnvs_ctx.rotate(this.rotate);
cnvs_ctx.translate(-absolute_x, -absolute_y);
// rotate translate point before continue
let tmp = this.helperRotatePoint(this.translate, -this.rotate);
// apply rotated translate
cnvs_ctx.translate(tmp.x, tmp.y);
} else {
cnvs_ctx.translate(this.translate.x, this.translate.y);
}
cnvs_ctx.scale(this.scale.x, this.scale.y);
cnvs_ctx.transform(1, this.skew.y, this.skew.x, 1, 0, 0);
// step 3: self draw (aka parent element)
cnvs_ctx.fillStyle = this.color;
cnvs_ctx.fillRect(absolute_x, absolute_y, this.draw_size.width, this.draw_size.height);
// step 4: draw childs elements
for (let i = 0; i < this.childs.length ; i++) {
elements_drawn += this.childs[i].draw(
cnvs_ctx, absolute_x, absolute_y
);
}
// done, restore state
cnvs_ctx.restore();
return elements_drawn;
}
}
// spawn some ui elements
var ui_panel = new UIElement(120, 50, 240, 140, "#9b9a9e");
var ui_textlabel = new UIElement(10, 10, 130, 18, "#FFF");
var ui_image = new UIElement(165, 25, 90, 60, "#ea9e22");
var ui_textdesc = new UIElement(17, 46, 117, 56, "#ff2100");
var ui_icon = new UIElement(5, 5, 10, 10, "#800000");
ui_panel.addChild(ui_textlabel);
ui_panel.addChild(ui_image);
ui_panel.addChild(ui_textdesc);
ui_textdesc.addChild(ui_icon);
// add some matrix transformations
ui_textdesc.skew.x = -0.13;
ui_textdesc.translate.x = 13;
ui_image.rotate = -90 * 0.017453292519943295;
ui_image.translate.y = ui_image.draw_size.width;
ui_panel.rotate = 15 * 0.017453292519943295;
ui_panel.translate.x = -84;
ui_panel.translate.y = -50;
// all ui element elements
ui_panel.draw(ctx, 0, 0);
<canvas width="480" height="360"></canvas>
I have read that you can make an array of anything. In my efforts to go forth in my studies of javaScript/canvas, I set out to create an array of shapes. The idea is to have an array of three circles. Math.floor will be used to grab one element/circle and display it on the canvas. I put together code that, well, makes sense to me... I've created an array, I have filled the array, I am grabbing a random element from the array... I have not yet reached the point of having to display it on the canvas, because not matter my approach, all three circles are always on the canvas. It would be so cool to grasp this concept. Can you tell me why this code doesn't work? Thank you in advance.
<script>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
var objects = [];
objects[0] =
[c.beginPath(),
c.lineWidth = 5,
c.strokeStyle = 'red',
c.arc(200, 200, 50, 0, Math.PI * 2, false),
c.stroke()];
objects[1] =
[c.beginPath(),
c.lineWidth = 5,
c.strokeStyle = 'dimgray',
c.arc(600, 200, 50, 0, Math.PI * 2, false),
c.stroke()];
objects[2] =
[c.beginPath(),
c.lineWidth = 5,
c.strokeStyle = 'purple',
c.arc(1000, 200, 50, 0, Math.PI * 2, false),
c.stroke()];
for (var i = 0; i < objects.length; i++) {
objects[i] = Math.floor(Math.random() * 3);}
</script>
You should make a function drawCircle which takes a canvas and a color as arguments
const drawCircle = (canvas, color = "red") =>
{
canvas.beginPath ()
canvas.lineWidth = 5
canvas.strokeStyle = color
canvas.arc (95, 50, 40, 0, 2 * Math.PI)
canvas.stroke ()
}
const getCanvas = (id) =>
document.getElementById(id).getContext("2d")
drawCircle (getCanvas('canvas-1')) // default "red"
drawCircle (getCanvas('canvas-2'), 'dimgray')
drawCircle (getCanvas('canvas-3'), 'purple')
<canvas id="canvas-1"></canvas>
<canvas id="canvas-2"></canvas>
<canvas id="canvas-3"></canvas>
We could add additional parameters for position, radius, and line width, but then how would we know which order to pass them in? A better option would be to pass a descriptor object with default values.
const drawCircle = (canvas, descriptor = {}) =>
{
const { x = 95
, y = 50
, radius = 40
, lineWidth = 5
, color = "red"
} = descriptor
canvas.beginPath ()
canvas.lineWidth = lineWidth
canvas.strokeStyle = color
canvas.arc (x, y, radius, 0, 2 * Math.PI)
canvas.stroke ()
}
const getCanvas = (id) =>
document.getElementById(id).getContext("2d")
drawCircle (getCanvas('canvas-1')) // default styles
drawCircle (getCanvas('canvas-2'), { color: 'dimgray' })
drawCircle (getCanvas('canvas-3'), { color: 'purple', radius: 10 })
<canvas id="canvas-1"></canvas>
<canvas id="canvas-2"></canvas>
<canvas id="canvas-3"></canvas>
Above, we use a named parameter descriptor but we could also could've inlined it. Because the descriptor contains so many properties, the readability suffers a bit and makes the previous version of our function a little nicer.
const drawCircle = (canvas, { x=95, y=50, radius=40, lineWidth=5, color="red" } = {}) => {
canvas.beginPath ()
canvas.lineWidth = lineWidth
canvas.strokeStyle = color
canvas.arc (x, y, radius, 0, 2 * Math.PI)
canvas.stroke ()
}
Now, using drawCircle you could create presets, like
const FatPurpleCircle = canvas =>
drawCircle (canvas, { color: "purple", lineWidth: 10 })
const SmallBlueCircle = canvas =>
drawCircle (canvas, { color: "blue", radius: 5 })
And you could have an array of these presets called circles. Given a function sample that returns a random element of an array, we can select a random circle function, and use it to draw its contents on a supplied canvas
const circles =
[ FatPurpleCircle, SmallBlueCircle, ... ]
const sample = (arr = []) => {
const size = arr.length
const rand = Math.floor (Math.random () * size)
return arr[rand]
}
const drawRandomCircle =
sample (circles)
drawRandomCircle (getCanvas('canvas-1'))
One option you have is to store each "canvas" in a function, which are then all stored in an array. This will end up having close to the same format that you had previously, but via a different method. #Patrick Roberts mentioned a similar method in his comment.
var objects = [
function() {
var canvas = document.getElementById("canvas-1");
var c = canvas.getContext("2d");
c.beginPath();
c.lineWidth = 5;
c.strokeStyle = 'red';
c.arc(95,50,40,0,2*Math.PI);
c.stroke();
},
function() {
var canvas = document.getElementById("canvas-2");
var c = canvas.getContext("2d");
c.beginPath();
c.lineWidth = 5;
c.strokeStyle = 'dimgray';
c.arc(95,50,40,0,2*Math.PI);
c.stroke();
},
function() {
var canvas = document.getElementById("canvas-3");
var c = canvas.getContext("2d");
c.beginPath();
c.lineWidth = 5;
c.strokeStyle = 'purple';
c.arc(95,50,40,0,2*Math.PI);
c.stroke();
}
];
objects[0]();
objects[2]();
objects[1]();
Here is a Codepen demonstrating this implementation.
As to why it doesn't work, #Xofox explained it very well in his comment:
[...] you can’t store lines of code in an array. c.arc(600, 200, 50, 0, Math.PI * 2, false) will execute that method, then return undefined. The array stores the result undefined.
how can I fill the "new" canvas circle that appears next to the older one.
There is no problem with rectangle for example:
**
ctx.fillStyle = 'rgba('+quadratto.r+','+quadratto.g+','+quadratto.b+',1)';
quadratto.x += quadratto.speedX;
quadratto.y += quadratto.speedY;
quadratto.speedY += quadratto.speedY*(-0.15);
ctx.fillRect(quadratto.x-quadratto.h/4, quadratto.y-quadratto.h/2, 2, 2);**
What I want to do?
I'm creating animation in canvas where random-sized-color circle will appear and
it will move in a specified direction. The new canvas layaer will appear in the next frame (fps) with a new(old) circle.
var myCanvasPattern = document.createElement('canvas');
myCanvasPattern.width = window.innerWidth;
myCanvasPattern.height = window.innerHeight;
document.body.appendChild(myCanvasPattern);
var ryC = myCanvasPattern.getContext('2d');
function lottery(min, max) {
return Math.floor(Math.random()*(max-min+1))+min;
}
var allQuadro = [];
var fps = 50;
var lastTime = 0;
animationLoop();
function animationLoop(time){
requestAnimationFrame( animationLoop );
if(time-lastTime>=1000/fps){
lastTime = time;
for(var i=0;i<10;i++){
allQuadro.push({
r : lottery(0, 240),
g : lottery(0, 240),
b : lottery(0, 240),
circleR : lottery(10, 30),
x : myCanvasPattern.width/2,
y : myCanvasPattern.height/2,
speedX : lottery(-1000,1000)/100,
speedY : lottery(-1000,1000)/100
})
}
ryC.fillStyle = 'rgba(255,255,255,0.2)';
ryC.fill(0,0,myCanvasPattern.width, myCanvasPattern.height);
for(var i=0; i<allQuadro.length;i++){
var circle = allQuadro[i];
ryC.fillStyle = 'rgba('+circle.r+','+circle.g+','+circle.b+',1)';
circle.x += circle.speedX;
circle.y += circle.speedY;
//HERE's THE PROBLEM BELOW. HOW TO CREATE NEW ONE THAT APPEARS NEXT TO PREVIOUS ONE WITH NEW RANDOM COLOR
ryC.arc(circle.x-circle.circleR/2, circle.y-circle.circleR/2, circleR, 0, 2 * Math.PI);
//ryC.fill();
}
// ryC.fillStyle = 'rgba('+r+','+g+','+b+',1)';
//ryC.arc(x+speedX, y+speedY, circleR, 0, 2 * Math.PI);
//ryC.fill();
}
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
The fillRect() will fill directly to the canvas without going via a path (versus for example rect()).
The arc() on the other hand will add to a path which needs to be filled later. It also require the path to be cleared in-between the calls using beginPath().
A simple way to think about it is to wrap the necessary code into a function that acts like fillRect():
function fillArc() {
ctx.beginPath(); // clear current path
ctx.arc.apply(ctx, arguments); // apply arguments to arc() call
ctx.fill();
// notice that the arc still exist on the path after this call
// so to "truly" behave like fillRect() you could consider an
// additional beginPath() here.. it will depend on your code
}
In action:
var ctx = c.getContext("2d");
ctx.fillStyle = "#09f";
fillArc(70, 70, 70, 0, 6.28);
ctx.fillStyle = "#0a9";
fillArc(220, 70, 70, 0, 6.28);
function fillArc() {
ctx.beginPath();
ctx.arc.apply(ctx, arguments);
ctx.fill();
}
<canvas id=c></canvas>
If you are bold you can also add the method to the context itself before calling getContext():
CanvasRenderingContext2D.prototype.fillArc = function() {
this.beginPath();
this.arc.apply(this, arguments);
this.fill();
}
The use it like any other method:
ctx.fillArc( ... );
CanvasRenderingContext2D.prototype.fillArc = function() {
this.beginPath();
this.arc.apply(this, arguments);
this.fill();
}
var ctx = c.getContext("2d");
ctx.fillStyle = "#09f";
ctx.fillArc(70, 70, 70, 0, 6.28);
ctx.fillStyle = "#0a9";
ctx.fillArc(220, 70, 70, 0, 6.28);
<canvas id=c></canvas>