unable to draw rectangle on canvas - javascript

I am drawing an image on a canvas with white background color. I want to draw a border on the image and I am unable to do so. Here is my code:
var canvas = parent.document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.fillStyle = "black";
context.font = "50px Arial";
//context.fillText(chartId, canvas.width-200, 50);
context.drawImage(image, 0, 0);
context.fillStyle = "#000000";
context.rect(0,0,canvas.width,canvas.height);
context.globalCompositeOperation = "destination-over";
context.fillStyle = "#FFFFFF";
But I don't see any border when I download this image.

You forgot to stroke your rect.
context.stroke();

There are two things missing.
is the context.stroke(); after painting your rect.
You should start drawing your rect() with context.beginPath();. This is to avoid the next stroke to also affect the first rectangle that you drew.
Another possible solution is to instead use the function context.strokeRect(); saving you the trouble of having to beingPath() and stroke().
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.fillStyle = "black";
context.font = "50px Arial";
//context.fillText(chartId, canvas.width-200, 50);
context.drawImage(image, 0, 0);
context.fillStyle = "#000000";
context.beginPath();
context.rect(0,0,canvas.width,canvas.height);
context.stroke();
context.globalCompositeOperation = "destination-over";
context.fillStyle = "#FFFFFF";

it looks like,you don't do the context.stroke() operation?

Related

Intersected semi-transparent stroke text

I have an issue with the painting context.stokeText that style contains an alpha. A big value of line width makes some effect of intersected strokes, as a result, the color is darker.
How I can avoid this?
ctx.strokeStyle ="rgba(0,0,0,0.3)";
ctx.lineWidth = 15;
ctx.lineJoin="round";
ctx.strokeText(text, x, y);
Image
That's a bit of an inconsistency in the specs since usually overlapping sub-pathes are painted only once.
However strokeText() does create one shape per glyph, and thus this method will indeed paint each glyphs on their own, creating this visible overlapping.
To overcome this, you'll to be a bit creative:
first draw your text fully opaque,
then redraw the produced pixels with the desired alpha level (many ways to do so).
draw that on your scene (or draw the background behind).
Here are a few ways (there are many others):
Probably the easiest, but which costs more memory: use a second disconnected canvas:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// create a new canvas just for the text
const canvas2 = canvas.cloneNode();
const ctx2 = canvas2.getContext("2d");
ctx2.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx2.measureText(text).width - 20;
const y = canvas.height - 20;
// draw it fully opaque
ctx2.lineWidth = 15;
ctx2.lineJoin="round";
ctx2.strokeText(text, x, y);
// draw the background on the visible canvas
ctx.fillStyle = "#ffe97f";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// now draw our text canvas onto the visible one
// with the desired opacity
ctx.globalAlpha = 0.3;
ctx.drawImage(canvas2, 0, 0);
<canvas width="465" height="234"></canvas>
More memory friendly, but which requires you to rewrite your drawing logic in a different direction, use compositing:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx.measureText(text).width - 20;
const y = canvas.height - 20;
// first draw the text fully opaque
ctx.lineWidth = 15;
ctx.lineJoin="round";
ctx.strokeText(text, x, y);
// now apply the opacity
ctx.fillStyle ="rgba(0,0,0,0.3)";
ctx.globalCompositeOperation = "source-in";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// and the background
ctx.fillStyle = "#ffe97f";
ctx.globalCompositeOperation = "destination-over";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// if you want to keep drawing "normaly"
ctx.globalCompositeOperation = "source-over";
<canvas width="465" height="234"></canvas>
A mix of both, with different compositing rules:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.font = "60px sans-serif";
const text = "MY TEXT";
const x = canvas.width - ctx.measureText(text).width - 20;
const y = canvas.height - 20;
// first draw the text fully opaque
ctx.lineWidth = 15;
ctx.lineJoin="round";
ctx.strokeText(text, x, y);
// now redraw over itself with the desired opacity
ctx.globalAlpha = 0.3;
ctx.globalCompositeOperation = "copy";
ctx.drawImage(canvas, 0, 0);
ctx.globalAlpha = 1;
// and the background
ctx.fillStyle = "#ffe97f";
ctx.globalCompositeOperation = "destination-over";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// if you want to keep drawing "normaly"
ctx.globalCompositeOperation = "source-over";
<canvas width="465" height="234"></canvas>

canvas resolution not good

i am trying to draw a canvas line on div id "myCanvas" but problem is the line becomes very low resolution and its not shows smooth line. How can i increase that line resolution? And make it smooth line?
js:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.rect(0, 0, canvas.width, canvas.height);
var grd = context.createLinearGradient(100, 150, canvas.width, canvas.height);
grd.addColorStop(0, '#0132bf');
grd.addColorStop(1, '#ccd9ff');
context.fillStyle = grd;
context.fill();
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.beginPath();
context.lineTo(-10, 190);
context.bezierCurveTo(200, -100, 500, 200, 400, 150);
context.lineWidth = .9;
context.strokeStyle = '#ccd9ff';
context.stroke();
jsfiddle link
Try giving your canvas HTML element width and height attributes that fit your requirements, for example:
<canvas id="myCanvas" width="600" height="600">

HTML Canvas - change text dynamically

I am trying to change the text on my html canvas while I type inside an input text field.
I can add the text however, if I delete and type again the new text is added on the top of the old one.
JSFIDDLE
document.getElementById('title').addEventListener('keyup', function() {
var stringTitle = document.getElementById('title').value;
console.log(stringTitle);
ctx.fillStyle = '#fff';
ctx.font = '60px sans-serif';
var text_title = stringTitle;
ctx.fillText(stringTitle, 15, canvas.height / 2 + 35);
});
This works. You just clear the canvas every time it's updated.
document.getElementById('title').addEventListener('keyup', function() {
var stringTitle = document.getElementById('title').value;
console.log(stringTitle);
ctx.fillStyle = '#0e70d1';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#fff';
ctx.font = '60px sans-serif';
var text_title = stringTitle;
ctx.fillText(stringTitle, 15, canvas.height / 2 + 35);
});
UPDATE
In case you only want to update the area where the text is, you can do just that,
ctx.fillRect(0, 130, canvas.width, 70);
Another approach would be, keeping track of the text as well as other objects in the canvas and refreshing the entire canvas. This is not as memory intensive as you'd think. If you want, you could also reset the canvas only when the text has been deleted (completely or partially), by comparing the previous string with new one.
You can save the state of the canvas, update the content, then restore it via:
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.fillStyle = '#0e70d1';
ctx.fillRect(0, 0, canvas.width, canvas.height);
document.getElementById('title').addEventListener('keyup', function () {
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(0, 0, canvas.width, canvas.height);
var stringTitle = document.getElementById('title').value;
ctx.fillStyle = '#fff';
ctx.font = '60px sans-serif';
var text_title = stringTitle;
ctx.fillText(stringTitle, 15, canvas.height / 2 + 35);
ctx.restore();
});
<canvas width="500" height="300" id="canvas">Sorry, no canvas available</canvas>
<input type="text" id="title" placeholder="Your Title" />
</br>
try replace last few line with this
ctx.fillStyle = '#0e70d1';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#fff';
ctx.fillText(stringTitle, 15, canvas.height / 2 + 35);
by canvas limitation, you must redraw whole canvas in order to update its content
I would add your text to an array and then clear the canvas after every time you type and redraw all the text.
As the letter are different widths and so are spaces and backspaces you can't be certain you will exactly clear the letter you want to delete.

set image insted of paint ball in javascript

I want to set an image instead of painting the ball
My code is the following
ballPainter = {
BALL_FILL_STYLE: 'rgb(255,0,50)',
BALL_STROKE_STYLE: 'rgb()',
paint: function (ball, context) {
var imageObj = new Image();
context.save();
context.shadowColor = undefined;
context.lineWidth = 2;
context.fillStyle = this.BALL_FILL_STYLE;
context.strokeStyle = this.BALL_STROKE_STYLE;
context.beginPath();
context.arc(ball.left, ball.top,
ball.radius, -1, Math.PI*2, false);
context.clip();
context.fill();
context.stroke();
context.restore();
}
},
You might want to check
http://www.w3schools.com/tags/canvas_drawimage.asp
I'm not sure if you can crop an image to a cricle though (maybe if the image has a transparant background)
*edit apperently you can HTML5 Canvas - Fill circle with image

Canvas use a letter instead of a shape?

I have written up an example, being new to canvas I need help transforming a basic circle into a letter.
Fiddle
Here is the code you will see in the fiddle. Note the circle drawing is what is in the center of the canvas, I am trying to use a letter like B with a cool font in place of the circle, I am just not sure how to implement this.
So just imagine where the circle is a letter being in that spot, still transparent with a rectangle overlaying the image with the color rgba(255,255,255,0.7).
var canvas = document.getElementById('c');
// resize the canvas to fill browser window dynamically
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
/**
* Your drawings need to be inside this function otherwise they will be reset when
* you resize the browser window and the canvas goes will be cleared.
*/
drawStuff();
}
resizeCanvas();
function drawStuff() {
if (canvas.getContext) {
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
// Full rectangle
context.fillStyle = 'rgba(255,255,255,0.7)';
context.fillRect(0, 0, window.innerWidth, window.innerHeight);
// Inner circle
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
// Add a letter instead of a circle?
// Hmm
context.fillStyle = 'rgba(0,0,0,1)';
context.globalCompositeOperation = 'destination-out';
context.fill();
}
}
why not
context.fillStyle = 'rgba(0,0,0,1)';
context.strokeStyle = "#F00";
context.font = "bold 60pt Arial";
context.globalCompositeOperation = 'destination-out';
context.fillText("B", 20, 50);
http://jsfiddle.net/pqD87/
Here again with centering
context.fillStyle = 'rgba(0,0,0,1)';
context.globalCompositeOperation = 'destination-out';
context.textAlign = 'center';
context.font="150px Times";
context.fillText("A",centerX,centerY+40);
http://jsfiddle.net/x4BuF/1/

Categories