When I run this code it produces the lines "rotating" from 0 degrees to 180, the problem is the previous line does not get cleared (so the ctx.clearRect(0,0,400,200) does not work. In the console log it shows up as running (when I try to debug) but it is not actually clearing it. Does anyone have any idea how to fix this?
var canvas = document.getElementById("radarImage");
var ctx = canvas.getContext("2d");
var angle = 0
function incrementAngle(){
angle++;
if(angle>180){
angle=0;
}
}
function rotateRadar(){
incrementAngle();
ctx.clearRect(0,0,400,200);
ctx.save();
ctx..translate(-200,-200);
ctx.rotate((Math.PI/180)*angle);
ctx.translate(-200,-200);
ctx.moveTo(200,200);
ctx.lineTo(0,200);
ctx.stroke();
ctx.restore;
}
setInterval(rotateRadar,200);
Edit: You should call your updates constantly using request animation frame: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
If you are open to using a library for working with canvas then easel js is could be a possibility: http://www.createjs.com/easeljs
Another SO user asked a similar question for Easel Js and there are some good answers that may be relavant to you: EaselJS - Rotate a shape around its center
Simply you cant rotate a line cont in canvas, you have to read sin,cos to rotate a line in canvas.
Hope this should help you.JsFiddle
context.clearRect(0,0,400,200);
context.beginPath();
context.moveTo(x,y);
x1=Math.cos(startAngle)*radius+10;
y1=Math.sin(startAngle)*radius+10;
console.log(x1,y1);
context.lineTo(x1,y1);
context.stroke();
Related
I observe weird behaviour of HTML canvas both in chrome and in firefox. For some reason there is one-pixel wide palid line when I fill rect over the smaller rect of different color after clipping.
Here is JS fiddle snippet: https://jsfiddle.net/srkgbxw1/7/
var my_canvas = document.getElementById('canvas'),
context = my_canvas.getContext("2d");
context.translate(0.5, 0.5)
context.fillStyle = "orange";
context.fillRect(10,10,100,100);
context.beginPath();
context.rect(20,20,90,90);
context.clip();
context.fillStyle = "white";
context.fillRect(0,0,110,110);
context.fillStyle = "orange";
context.fillRect(0,0,190,190);
This is the result:
Please help me figure out what the reason for the pallid line after third fillRect with orange?
UPD: original question's changed after I was pointed out I had made a stupid mistake in its first edition
UPD 2 I got the answer, this happens due to color interpolation at edges of clipping region because context was translated for half a pixel, which was done to get thin lines (recommended technique). To avoid interpolation, clipping region should be adjusted for half a pixel as well, then the pallid line disappears.
If you look into the logs:
TypeError: context.setStrokeStyle is not a function
Therefore, when you comment it, everything after it is executed while when you uncomment it, it fails and everything after this line is not executed.
EDIT: For the second question issue:
The issue is equivalent to this, why the blue square does not fully overlap the red square:
context.translate(0.5, 0.5);
context.fillStyle = "red";
context.fillRect(10,10,100,100);
context.fillStyle = "blue";
context.fillRect(10,10,100,100);
Because of translate, you are now drawing in float pixels, everything moved by half a pixel.
I suggest you read this for more information about how it is handled:
fillRect() not overlapping exactly when float numbers are used
Removing context.translate(0.5, 0.5); removes the "palid line".
I am searching for a solution to draw a border around all shapes on an Image. I have already tried this solution Draw border around nontransparent part of image on canvas but this doesnt work for me.
Imagine this png
the solution I am looking for should look like this
is there any libary/solution?
Thank you
If you're drawing the all the shapes using ctx.fill(), you can just call ctx.stroke() before each call to ctx.fill(). This will result in a line of width ctx.lineWidth/2, since half of the line will be covered by the shape itself. However, his won't work for other methods such as ctx.drawImage() or ctx.putImageData(). Please specify how exactly you're drawing these shapes to the canvas to receive some more detailed help.
Edit: I think you can use the solution you already mentioned, you just need to make the non-black part of your image transparent. You can do this by editing the the imageData of the canvas:
var ctx = canvas.getContext("2d");
var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
for (let i=0;i<imageData.data.length;i+=4){
if (shouldBeTransparent(imageData.data[i],imageData.data[i+1],imageData.data[i+2]){
imageData.data[i+3] = 0;
}
}
ctx.putImageData(imageData,0,0);
function shouldBeTransparent(r,g,b){
return r!=0||g!=0||b!=0;
}
This will make all pixels that are not entirely black transparent, so you can continue with the method you already mentioned.
I am creating a html5 canvas game and the main idea is that there is a loop at every animation that redraws everything on my canvas in every frame.
For some reason the objects drawn don't appear in the order i want them to. i want the background image first, then a rectangle and finally an other image to be shown on top of each other.However, the rectangle blocks the view of the second image not other way around.
my relevant code:
function playerdraw(p){
ctx.rect(p.x,p.y,100,150);
ctx.stroke();
//irrelevant stuff here...
ctx.drawImage(p.im,p.x,p.y+25,100,100);
}
I run the whole thing on window.onload so image loading shoudn't be a problem.
Why is this happening?
(as you haven't provided enough code, I assume this could be the issue.)
You need to redraw the background image each time you run the playerdraw() function (if you're clearing the entire canvas each time). So, the following code should work :
function playerdraw(p) {
// clear entire canvas
ctx.clearRect(...);
// draw background image
ctx.drawImage(...);
// draw rectangle
ctx.rect(p.x, p.y, 100, 150);
ctx.stroke();
// irrelevant stuff here...
// draw other image
ctx.drawImage(p.im, p.x, p.y + 25, 100, 100);
}
Note: You need to clear the entire canvas at the very beginning (if you're doing so). There's is also a possibility that you're doing some kind of canvas translating or scaling stuff which if done in wrong order, things can get pretty messed up.
I now know what my issue was. I forgot to add
ctx.beginPath();
in my code. I called my function again and again and it drew more rectangles then I wanted to. I feel so silly.
So I have a semi-complex canvas drawing someone gave me. It draws an image vertically (i.e., top-down). Let's assume its a stick figure with facial features.
This is done in Javascript and Canvas. i.e.: ctx.beginPath(), ctx.moveTo(x,y), ctx.lineTo(1,1), etc.
I want the stick figure to move towards some point (x,y) and to face that direction while moving toward it. For example, if the x,y is near the bottom right, I want the stick figure to be oriented in a way such that its feet are facing towards the bottom right while it is moving.
The main question is, how would I go about doing this (i.e changing the stickman), knowing that I have a "hardcoded" drawing (in this example, stickman) that has been given to me?
You can render the received image on a separate canvas (doesn't need to be displayed) and use ctx.canvas.toDataURL() to convert it to an image. You could then embed the resulting image in your canvas and apply transforms to it more easily.
I mentioned this in a comment on the question but it sounded like fun, so I implemented a proof of concept.
var canvasObject = function(ctx) {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(30,30,15,0,2*Math.PI);
ctx.fillStyle='red';
ctx.fill();
return ctx;
}
var myCtx = document.querySelector('canvas').getContext('2d');
var objCtx = document.createElement('canvas').getContext('2d');
var renderedObjUrl = canvasObject(objCtx).canvas.toDataURL();
var renderedObj = document.createElement('img');
renderedObj.setAttribute('src', renderedObjUrl);
myCtx.drawImage(renderedObj, 30, 10);
<canvas id="myCanvas" width="600" height="400"></canvas>
I'm using JQueryKnob and trying to add segments to the radial. I'm not well versed in Canvas drawing, so that didn't seem like the best road to take - what I really need to do is just overlay a mask image on the drawn Knob canvas element. I've tried variations of this and it doesn't seem to work (I'm guessing the mask can't apply to canvases?)
I started to dabble with trying to just draw alpha'd lines in the JQueryKnob draw method, but didn't really have any luck with that either.
Any ideas? I'm pretty lost here
You're on the right track...just draw your masked image inside the draw method of your knob.
$(".knob").knob({
draw : function () {
var ctx=this.g;
var x=this.xy;
var y=this.xy;
var r=this.radius;
var iw=img.width;
var ih=img.height;
ctx.save();
ctx.beginPath();
ctx.arc(x,y,r,0,Math.PI*2);
ctx.clip();
ctx.drawImage( img, 0,0,iw,ih, x-iw/2,y-ih/2,iw,ih );
ctx.restore();
}
});
Here's example code and a Demo: https://jsfiddle.net/m1erickson/g8rx58hh/