I need to delete the line which was previously drawn by putting another line over it. The new line should be the same color as the background.
I tried:
http://jsfiddle.net/wgenf10x/
<canvas id="canvas" style="background-color: black;">
Javascript:
var canvas = document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var screenW = canvas.width;
var screenH = canvas.height;
setColor("#ffffff");
draw();
function setColor(colorHexStr){
ctx.strokeStyle = colorHexStr;
}
function line(x1,y1,x2,y2){
ctx.moveTo(x1,y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function draw(){
setColor("white");
line(0,0,screenW, screenH);
setColor("black");
line(0,0,screenW, screenH);
}
But the white line is not completely erased. What is going wrong?
P.S. Please do not suggest clearing the whole canvas. I don't need it.
You are seeing artifacts created by canvas's automatic anti-aliasing.
Just increase the "erasing" lineWidth (ctx.lineWidth+=1;) to also over-write that anti-aliasing.
Related
On my application I have to draw separate lines. One line solid and one line dashed. I am using the CanvasRenderingContext2D. My problem is how can I draw one dotted line and one solid line using the same context. What I have tried is:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.setLineDash([2, 2])
ctx.moveTo(50, 50); // Begin first sub-path
ctx.lineTo(200, 50);
ctx.moveTo(50, 90); // Begin second sub-path
ctx.lineTo(280, 120);
ctx.stroke();
But it draws lines as dotted. It makes sense why, because I am using the same context for both lines but I need to use the same context in my app. I just gave a minimal example. Is there a way to do this?
In a canvas I would recommend to use some sort of prototype to represent a point in your coordinate system. Then you can simply pass the points to your drawLine function and pass an additional style.
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
function Point(x, y) {
this.x = x;
this.y = y;
}
function drawLine(from, to, style=[]) {
ctx.beginPath();
ctx.setLineDash(style)
ctx.moveTo(from.x, from.y);
ctx.lineTo(to.x, to.y);
ctx.stroke();
ctx.closePath();
}
drawLine(new Point(50, 50), new Point(200, 50)); // solid line
drawLine(new Point(50, 90), new Point(280, 120), [2,2]); // dashed line
<canvas id="canvas" width="500" height="500"></canvas>
I want to know how to rotate a line in canvas.
Say I have the canvas set-up.
ctx.beginPath();
ctx.strokeStyle = "#000000";
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.closePath();
How do I rotate this line?
Thanks,
Alex
Here's how to rotate a line segment between p1 & p2 around that segment's midpoint:
The idea is to:
Save the unrotated state of the context using context.save
Set the rotation point at the midpoint of the line using context.translate
Rotate to a specified radian angle using context.rotate
Draw the line. This is the tricky part...Since the canvas is already rotated and since the canvas origin is now the line's midpoint, you must moveTo minus the line's length/2 and lineTo the lines length/2: context.moveTo(-length/2,0); and context.lineTo(length/2,0);
Restore the context to its unrotated state with context.restore
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var p1={x:75,y:75};
var p2={x:150,y:150};
var dx=p2.x-p1.x;
var dy=p2.y-p1.y;
var length=Math.sqrt(dx*dx+dy*dy);
var angle=Math.atan2(dy,dx);
var midX=(p2.x+p1.x)/2;
var midY=(p2.y+p1.y)/2;
console.log(midX,midY);
draw(angle);
requestAnimationFrame(animate);
function animate(time){
requestAnimationFrame(animate);
draw(angle);
angle+=Math.PI/30;
}
function draw(radianAngle){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
ctx.translate(midX,midY);
ctx.rotate(radianAngle);
ctx.beginPath();
ctx.strokeStyle='red';
ctx.moveTo(-length/2,0);
ctx.lineTo(length/2,0);
ctx.stroke();
ctx.restore();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>
Note: This code shows rotation around your line's midpoint, but you can rotate around any point by using context.translate(anyRotationPointX,anyRotationPointY);
To rotate anything you can use context method - rotate().
We can't rotate line like object (like in SVG), but we can - redraw canvas with new rotated line.
var canvas = document.getElementById("example"),
ctx = example.getContext('2d'),
canvasWidth = canvas.width,
canvasHeight = canvas.height,
p1 = {x:canvasWidth/2+50,y:canvasHeight/2},
p2 = {x:p1.x,y:p1.y+100},
middlePoint = {x:(p1.x+p2.x)/2,y:(p1.y+p2.y)/2};
function rotate(degree,rotatePoint,drFunc) {
rotatePoint = rotatePoint || {x:canvasWidth/2,y:canvasHeight/2};
// Clear the canvas
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Move registration point to the center of the canvas
ctx.translate(rotatePoint.x, rotatePoint.y);
// Rotate 1 degree
ctx.rotate((Math.PI / 180)*degree);
// Move registration point back to the top left corner of canvas
ctx.translate(-rotatePoint.x, -rotatePoint.y);
drFunc();
}
function drFunc(){
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
ctx.closePath();
}
rotate(1,middlePoint,drFunc);
Fiddle
I want to draw a line with one color, and the next line with a different color. But when I call stroke() the second time, the first line is draw again! How can I avoid it? Here's my code:
var canv = document.getElementById("canvas");
var ctx = canv.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(100,100);
ctx.strokeStyle = "#FF0000";
ctx.stroke();
ctx.moveTo(100,100);
ctx.lineTo(100,200);
ctx.strokeStyle = "#999999";
ctx.stroke();
Thanks in advance!
Just insert a beginPath() in there:
var canv = document.getElementById("canvas");
var ctx = canv.getContext("2d");
ctx.moveTo(0,0);
ctx.lineTo(100,100);
ctx.strokeStyle = "#FF0000";
ctx.stroke();
cxt.beginPath(); // <---
ctx.moveTo(100,100);
ctx.lineTo(100,200);
ctx.strokeStyle = "#999999";
ctx.stroke();
That will reset your path. A stroke just strokes what exists on the path but does not clear it. You will have to manually reset the path for each new shape you want to draw.
The advantage is that you can reuse the path for fill, clip and point testing. The disadvantage is that it's easy to forget sometimes.
I am trying to figure out how one can detect if the user's mouse hits a line on an HTML 5 canvas with jQuery.
Here is the code that generates the canvas lines:
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript">
window.onload = function(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.moveTo(40,0);
ctx.lineTo(40,360);
ctx.stroke();
ctx.moveTo(80,400);
ctx.lineTo(80,40);
ctx.stroke();
ctx.moveTo(120,0);
ctx.lineTo(120,360);
ctx.stroke();
ctx.moveTo(160,400);
ctx.lineTo(160,40);
ctx.stroke();
};
</script>
I'm using a modified jQuery script that I actually found in another question on here, but now I can't figure out how to detect the line, mainly the difference in color from white to black, in the canvas. I know that this can be done with images, but I haven't seen anyone with something like this.
I guess my real question is, is there a way to detect color changes on a canvas element with jQuery?
Its possible to do with javascript. In fact you aren't using any jQuery in your example above. An easy way to do it is by grabbing the pixel data from the canvas, and checking the alpha at the specified x and y position. If the alpha isn't set to 0, then you have something drawn on the canvas. Below is a function I put together real quick that does that.
Live Demo
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 400;
height = 400;
canvas.width = canvas.height = 200;
// draw
ctx.moveTo(40, 0);
ctx.lineTo(40, 360);
ctx.stroke();
ctx.moveTo(80, 400);
ctx.lineTo(80, 40);
ctx.stroke();
ctx.moveTo(120, 0);
ctx.lineTo(120, 360);
ctx.stroke();
ctx.moveTo(160, 400);
ctx.lineTo(160, 40);
ctx.stroke();
function detectLine(x, y) {
var imageData = ctx.getImageData(0, 0, width, height),
inputData = imageData.data,
pData = (~~x + (~~y * width)) * 4;
if (inputData[pData + 3]) {
return true;
}
return false;
}
canvas.addEventListener("mousemove", function(e){
var x = e.pageX,
y = e.pageY;
console.log(detectLine(x, y));
});
console.log(detectLine(40, 100));
console.log(detectLine(200, 200));
I'm trying to make a website where an image is drawn on Canvas, then later the user is able to press a button to ctx.fill() certain parts of it with color. I'm running into issues where I can only ctx.fill() the most recently created shape which often isn't the shape I want.
Here's an example. In this code (live at http://build.rivingtondesignhouse.com/piol/test/) I'm trying to draw the first rectangle, then save() it on the stack, then draw the second rectangle (and don't save it), then when my fill() function is called I want to restore() the first rectangle and ctx.fill() it with a different pattern. It doesn't work!
In practice, I'm actually trying to fill the gray part of this complex shape with any color the user chooses AFTER the image has been drawn, but I think the technique is the same. (http://build.rivingtondesignhouse.com/piol/test/justTop.html)
Thanks in advance for any help!!!
Here's the code:
<script type="text/javascript">
var canvas;
var ctx;
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
draw();
}
function draw() {
ctx.fillStyle = '#FA6900';
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
ctx.shadowBlur = 4;
ctx.shadowColor = 'rgba(204, 204, 204, 0.5)';
ctx.fillRect(0,0,15,150);
ctx.save();
ctx.fillStyle = '#E0E4CD';
ctx.shadowOffsetX = 10;
ctx.shadowOffsetY = 10;
ctx.shadowBlur = 4;
ctx.shadowColor = 'rgba(204, 204, 204, 0.5)';
ctx.fillRect(30,0,30,150);
}
function fill(){
var image = new Image();
image.src = "http://www.html5canvastutorials.com/demos/assets/wood-pattern.png";
image.onload = drawPattern;
function drawPattern() {
ctx.restore();
ctx.fillStyle = ctx.createPattern(image, "repeat");
ctx.fill();
}
}
init();
There are a few misunderstands that we need to clear up before I can answer the question.
save() and restore() do not save and restore the canvas bitmap. Instead they save and restore all properties that are set on the canvas context and that's all!
For example
ctx.fillStyle = 'red';
ctx.save(); // save the fact that the fillstyle is red
ctx.fillStyle = 'blue'; // change the fillstyle
ctx.fillRect(0,0,5,5); // draws a blue rectangle
ctx.restore(); // restores the old context state, so the fillStyle is back to red
ctx.fillRect(10,0,5,5); // draws a red rectangle // draws a red rectangle
See that code live here.
So you aren't saving a rectangle (or anything drawn) by calling save(). The only way you you can save the bitmap is by drawing it (or part of it) to another canvas (using anotherCanvasContext.drawImage(canvasIWantToSave, 0, 0)) or by saving enough information that you can redraw the entire scene with the appropriate changes.
Here is an example of one way you could re-structure your code so that it does what you want: http://jsfiddle.net/xwqXb/