I am currently using a html5 canvas and by using ionic 2 (tap)="markPoint($event)" on the canvas in html, I am getting the position of the tap event. Below is the function which should place the mark:
public markPoint(event) {
var position = event.center;
let ctx = this.canvas.getContext('2d');
ctx.beginPath();
ctx.arc(position.x, position.y, 20, 0, 2 * Math.PI);
ctx.fillStyle = '#00DD00';
ctx.fill();
}
I am setting the canvas like so, where canvas is the id set in the html:
this.canvas = document.getElementById('canvas');
I don't see an issue with this code, however I am also not sure whether or not this is the best way to make marks within an application in ionic 2. Do you know if this should work, and if not why? Also if there are any better ways it would be awesome to here about them.
First of all we have to make more typescript<6> friendly. It's not enough just to get the canvas object like another HTML element using the id. In this case we should help a little, so my first change will be:
this.canvas = document.getElementById('canvas');
FOR =>
this.canvas = <HTMLCanvasElement>document.getElementById('canvas');
Then your function will look something like this:
public markPoint(event) {
var position = event.center;
let ctx: CanvasRenderingContext2D = this.canvas.getContext("2d");
ctx.beginPath();
ctx.arc(position.x, position.y, 20, 0, 2 * Math.PI);
ctx.fillStyle = '#00DD00';
ctx.fill();
}
Hope this help.
Related
I am trying to make a simple "game" in HTML5 (mainly Javascript), where you simply move a ball around.
I would like to create a ball (which can be moved with arrow keys) by drawing a circle on canvas. Is this possible, or is another approach simpler?
I would like to create it as a function, so that I have a means for selecting the ball.
Anyways, I am able to draw a triangle, but not a circle. This is the code:
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
canvas.width = canvas.height = 500;
function circle() {
// the circle - DOESNT SHOW UP
ctx.beginPath();
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fillStyle = "blue";
ctx.fill();
}
cicle();
function drawTriangle() {
// the triangle - works perfectly
ctx.beginPath();
ctx.moveTo(200, 100);
ctx.lineTo(170, 150);
ctx.lineTo(230, 150);
ctx.closePath();
// the fill color
ctx.fillStyle = "rgba(255, 204, 0, 1)";
ctx.fill();
}
drawTriangle();
Can anyone figure, why the circle doesn't appear?
IMPORTANT: The circle appears perfectly, when it is NOT part of a function
P.S.: Im very new to web development etc.
Thanks for any advice
Is it possible that that is due to the typo when you call the circle function? So circle() instead of cicle()
Well, it is quite simple. When you call a function in javascript, you must spell it the same as in the function declaration otherwise you will be calling a function that does not exist.
function circle(){
//code to draw circle
}
//then when i want to call circle function i do this
circle();
//this calls non-existant "cicle" function
cicle();
So, there is nothing wrong with your function, just how you called it.
var ctx = space.getContext("2d");
var FPS = 40;
var score = 0;
function scoring(){
ctx.font = "20px Helvetica";
ctx.fillStyle = "#001e52";
if(score<10){
ctx.fillText(score, center.x+44.5, center.y+57);
}
if(score>=10 && score<=99){
ctx.fillText(score, center.x+38.9, center.y+57);
}
if(score>=100 && score<=999){
ctx.fillText(score, center.x+33, center.y+57);
}
if(score>=1000){
score=0;
}
}
setInterval(scoring, 1000/FPS);
The code above was working on another canvas game I made exactly as presented. Now I copied and pasted it in my new game and it doesn't work (I obviously changed the coordinates and all to fit my new game). When inspecting element on Chrome it gives me this weird error: Uncaught TypeError: ctx.fillText is not a function Any ideas what could be happening?
I had to delete a previous instance of the fillText function in order for it to draw the score on the canvas. No idea why, but it worked.
I had the same problem. I looked more carefully and it was filltext(some arguments).
Problem was I was writing it with small T, not with camelCase.
I'm reading through an article about continuously drawing frames of an HTML5 video player on canvas. I heard about JS iterators a while back and I think there's supposedly a performance advantage, so I'd like to know how to write this set of canvas painting functions into an Iterator:
function canvasVideo(){
//DECLARE VARIABLES
var $videoPlayer = $('#Video-Player');
var $canvasPlayer = $('#Canvas-Player');
var videoPlayer = $videoPlayer[0];
var canvasPlayer = $canvasPlayer[0];
var context = canvasPlayer.getContext("2d");
//DEFINE FUNCTIONS
//draw the video
function draw() {
//Background
context.fillStyle = '#ffffaa';
context.fillRect(0, 0, canvasPlayer.width, canvasPlayer.height);
//video
context.drawImage(videoPlayer , 0, 0);
}
//update canvas at set interval with video frames
function canvasRun(int){
//set timer with interval
var canvasTimer = setTimeout(canvasRun, int);
//draw the video frame
draw();
}
function videoLoaded(event){
canvasRun(20);
}
//HANDLE EVENTS
$videoPlayer.on("canplaythrough", function (){
videoLoaded();
});
}
How can this be done with JS Iterators?
I've tried using tutorials to learn iterators, but the generic examples have confused me, and think seeing it done with an example like this would help me learn.
I am creating a simple drawing app using the HTML5 canvas element. The program logic works fine, and everything runs great, except for one thing.
When I draw the first line, the mouse coordinates and the line match perfectly. However, after each subsequent line, the coordinates of the line being drawn are about 0.5~1px off. These discrepancies accumulate, and the effect is readily visible after drawing about ten separate lines. This occurs in all browsers.
For a live example, check this fiddle. I have stripped down everything as much as I could. Obviously the real app is a lot more complex, but even in this simplified version the problem persists, which leads me to think I'm missing something incredibly obvious.
It occurred to me that I might be somehow rounding up the coordinates, which is about the only thing I can think of that could account for such a gradual drift. I was using a proprietary function for getting the offset values, so I tried using jQuery (since that has never given me problems in the past) but nothing changed.
Please help me figure out why this is happening!
Apparently I need to post code now in order to link to jsfiddle. I have no idea which part of the code might be wrong, so I apologise in advance for posting everything and creating a wall of text.
var offsetX = 0, offsetY = 0;
var currentMouseCoords = {
x : 0,
y : 0
};
var drawPing = null;
var ctx = null;
$('#cover').mousedown(function (event) {
event.preventDefault();
var f = $(this).offset();
offsetX = f.left;
offsetY = f.top;
currentMouseCoords.x = event.pageX - offsetX;
currentMouseCoords.y = event.pageY - offsetY;
drawStart();
if (!drawPing) {
drawPing = setInterval(draw, 10);
}
})
.mousemove(function (event) {
currentMouseCoords.x = event.pageX - offsetX;
currentMouseCoords.y = event.pageY - offsetY;
})
.mouseout(function (event) {
//When mouse leaves canvas, quit drawing
drawEnd();
})
.mouseup(function (event) {
//When mouse leaves canvas, quit drawing
drawEnd();
})
/* Functions that perform the actual drawing */
function drawStart () {
//Get canvas context
ctx = document.getElementById('canvas').getContext("2d");
ctx.translate(0.5,0.5);
//Set styles
ctx.strokeStyle = '#333333';
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.lineWidth = 1;
//Begin path
ctx.beginPath();
ctx.moveTo(
currentMouseCoords.x,
currentMouseCoords.y
);
}
function draw () {
ctx.lineTo(
currentMouseCoords.x,
currentMouseCoords.y
);
ctx.stroke();
}
function drawEnd () {
clearInterval(drawPing);
drawPing = null;
if (ctx) {
ctx.closePath();
ctx = null;
}
}
I imagine it'll make a lot more sense if you just look at the actual fiddle....
For the record, I googled for quite a while to see if anyone else had this issue, but either it's not that common or I can't find the right combination of words. There are myriad problems with mouse coordinates but none of them seem to be the same as the one I am experiencing.
You are repeatedly translating in your drawStart function and those translations are accumulating:
ctx.translate(0.5,0.5)
You can reverse the translate with translate(-.5,-.5) or wrap your drawing code in ctx.save()/ctx.restore().
You might also want to move your ctx=document... outside the drawStart "loop" for better performance.
//Get canvas context outside drawStart
ctx = document.getElementById('canvas').getContext("2d");
Is there any point in pre-rendering images on canvas?
An example,
var img; // Img object
var pre = document.createElement("canvas");
pre.width = img.width;
pre.height = img.height;
var precon = pre.getContext("2d");
precon.drawImage(img, 0, 0);
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
for(var i =0; i < 10000; ++i) {
ctx.drawImage(pre, Math.random() * canvas.width, Math.random() * canvas.height);
}
I don't see the point as you are still calling context.drawImage no matter what you do, unless the canvas api is faster drawing an image from a canvas object rather than image object?
Firstly, I must say that your example is not suitable to highlight the need and benefits of canvas pre-rendering.
I'll give you a better example were you need to draw multiple times something that requires heavy computation on a canvas.
Let's say you have this draw function :
function complexDraw(ctx){
ctx.drawImage(img, width, height);
// heavy computation goes here
// some transforms maybe
ctx.ctx.setTransform(-1, 0, 0, 1, 200, 200);
ctx.fillStyle = "rgba(100, 100, 255, 0.5)";
ctx.fillRect(50, 50, 100, 100);
//maybe draw another img/video/canvas
ctx.drawImage(anotherImg, width, height);
// ...
}
function draw(){
complexDraw(ctx);
}
Now let's say you want to show the current time on the canvas too. That means that we're going to add this at the bottom of our draw function :
function drawTime(ctx){
ctx.fillText(new Date().getTime(), 10, 50);
}
And now our draw function looks like this :
function draw(){
complexDraw(ctx);
drawTime(ctx);
}
Since you want to always show the current time, you need to call the draw function every second :
setInterval(draw, 1000);
This actually means that every second you are doing some heavy computation just to update a silly little text.
If only there could be a way to split the draw function and compute only the things that need computing (the ones that change)... but there is: say hello to canvas pre-rendering!
The key idea is to draw the part that doesn't change (and doesn't need to be re-computed) on a separate canvas - let's call it cacheCanvas - and just copy it's content on our app's canvas whenever we want to redraw stuff :
// suppose we have a `clone` function
var cacheCanvas = clone(canvas),
cacheCtx = cacheCanvas.getContext('2d');
// let's draw our complex stuff on the cacheCanvas
complexDraw(cacheCtx);
// modify our main `draw` function to copy the result of the `complexDraw`
// function, not to call it
function draw(){
ctx.drawImage(cacheCanvas, width, height);
drawTime();
}
And now we're basically redrawing the whole canvas each second, but we're not re-computing all the heavy work in complexDraw.
I just want to note that most of the canvas based games can't run at 60fps (redraw 60 times per second) without doing some performance boost with pre rendering or another technique called canvas layering (which is also worth looking into).