How can i draw a canvas with Image and Text where text is updated with new values periodically.
The problem i face is that the new text is writing on the old text without clearing it.
<canvas id="product1" width="184" height="239"/>
var img = new Image();
img.onload = function () {
context.drawImage(img, 0, 0, img.width,img.height,0, 0, 184, 239);
context.font = "20pt Calibri";
context.textAlign="center";
context.fillText("Product 1",150,120);
};
img.src = "https://image.ibb.co/gWNAoa/KEG.jpg";
setInterval(function() {
var context = document.getElementById('product1').getContext("2d").fillText(Math.random(),150,120);
}, 2000);
You have to clear canvas, redraw image and draw new text.
Or if you know the place of the text, clear only the rect where text is and draw new text.
Use clearRect(x,y,width,height)
Canvas is like a paper where you have magic pencil that can write upon what you have drawn. You can't select particular object like line, text, rect, image or whatever you have drawn. You can just clear and write.
Related
I have 3 canvases. I crop a region from canvas1 and display it on canvas 2 . Then I want to convert canvas 2 image to a URL and to see if can convert that URL back to a image. I want it to be displayed in canvas c4.Any help is appreciated.
// image is drawn here , I want this image to be converted to a dataURL
//then back to image and display it in canvas c4
var c2 = document.getElementById("area_c2");
var ctx = c.getContext("2d");
var ctx2 = c2.getContext("2d");
image_src.width = c2.width;
image_src.height = c2.height;
ctx2.drawImage(image_src, 0, 0,image_src.width, image_src.height);
var c4 = document.getElementById("area_c4");
var ctx4 = c4.getContext("2d");
var dataURL = c2.toDataURL();
var myImg = new Image;
myImg.src = dataURL;
myImg.width = c4.width;
myImg.height = c4.height;
ctx4.drawImage(myImg, 0, 0, image_src.width, image_src.height); //Image //is not displayed here , I want the image to take the size of the canvas
<canvas id ="area_c2" style="width:300px;height:300px;border:3px solid
black;z-index:1" >
</canvas>
<canvas id ="area_c4" style="width:300px;height:300px;border:3px solid
black;z-index:1;background:red">
</canvas>
The reason your solution did not work is because you did not wait for the onload event. Before the onload event the image will not render.
To convert a canvas to a data URL is simple, use the .toDataURL(); method of the canvas element.
Then to convert the data URL back to an canvas image, you would first have to create an Image element and set its source as the dataURL. After getting the image onload event you can draw the image onto the canvas. This could be accomplished as shown:
Assuming the data URL is in a variable called dataURL, the canvas context is in a variable called ctx.
var img = new Image;
img.onload = () => { ctx.drawImage(img, 0, 0); };
img.src = dataURL;
The final solution would go like this:
var cdata2 = c2.toDataURL();
var cimg2 = new Image;
cimg2.onload = () => { ctx4.drawImage(cimg2, 0, 0, c4.width, c4.height); };
PS: You don't have to scale the image object by specifying the width and height, the canvas will do that when you specify the destination width and height.
I'm using html5 canvas to make a game. I made a spritefont system to be able to draw text from a texture. Namely
.
Now I'd like to be able to change the white part of the text to any color I want. My guess is that I'll need to render the texture to a temporary canvas change the color and get the new texture and draw that instead.
However, I don't know how I can replace a color using the canvas's functions.
And I don't even know if this is the best way to do this. What should I do?
Since your spritefont is monochrome, you can use CanvasRenderingContext2D's 'multiply' globalCompositeOperation to apply color to the white part. But multiplying by a solid rectangle of color will wipe out the transparency, so you'll need to redraw the transparent parts with 'destination-atop'.
const FONT_COLOR = '#39f';
// Load up your spritefont
const spritefont = new Image();
spritefont.src = 'https://i.stack.imgur.com/mDvum.png';
// While waiting for the image to load,
// create a canvas to do the coloring work on
const fontCanvas = document.createElement('canvas');
const fontContext = fontCanvas.getContext('2d');
// Once the spritefont is loaded,
spritefont.addEventListener('load', function () {
// Resize the canvas to match the image's dimensions
fontCanvas.width = spritefont.width;
fontCanvas.height = spritefont.height;
// Draw your image on the canvas with a black background
// Without the background, you'll get tinting at the partially-transparent edges
fontContext.fillStyle = 'black';
fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
fontContext.drawImage(spritefont, 0, 0);
// Multiply by the font color
// white * color = color, black * color = black
fontContext.globalCompositeOperation = 'multiply';
fontContext.fillStyle = FONT_COLOR;
fontContext.fillRect(0, 0, fontCanvas.width, fontCanvas.height);
// Restore the transparency
fontContext.globalCompositeOperation = 'destination-atop';
fontContext.drawImage(spritefont, 0, 0);
});
// Display the canvas in the snippet
document.body.append(fontCanvas);
/* just to prove that alpha is preserved */
canvas {background:0 0/32px 32px linear-gradient(45deg,#ccc 25%,transparent 25%,transparent 75%,#ccc 75%,#ccc),16px 16px/32px 32px linear-gradient(45deg,#ccc 25%,#999 25%,#999 75%,#ccc 75%,#ccc);}
If you plan to put the color-changing functionality in a function and reuse the canvas (which you should), make sure to set the context's globalCompositeOperation back to the default, 'source-over'.
HTML5 canvases follows draw and forget strategy. If you want any change (be it font color or change of shapes or text or lines etc) in what had been drawn earlier, you need to re-draw everything.
Mostly upto to my use of canvases, the whole re-drawing process is pretty fast and works without any lag or delay.
EDIT
context.fillStyle = 'red';
context.strokeStyle = 'black';
context.font = '20pt Verdana';
context.fillText('Some text', 50, 50);
context.strokeText('Some text', 50, 50);
context.fill();
context.stroke();
I am loading a picture into a canvas; I drawImage(), store getImageData() into a variable for manipulating. I would like to be able to manipulate the data many times for example: add/remove various filters. How can I store the data so that it updates every time I draw the picture with putImageData()?
Basically, I think I am misunderstanding the use of getImageData or using it incorrectly. My thought was that any manipulation that was done to the picture, I could run getImageData and update the variable that contained the information, and use it to "redraw" the picture.
Example:
In the snippet below Lets say I run a function that turn the picture black and white. I have another function that resizes the picture when it is clicked. When I resize the picture the the black and white filter disappears. What am I doing wrong to keep the information of the picture?
//Read in picture
var reader = new FileReader();
reader.onload = function leDraw(e){
imgObj = new Image();
picWidth = canvas.width/2;
picHeight = canvas.height/2;
imgObj.src = e.target.result;
newX = 0;
newY = 0;
ctx.drawImage(imgObj,0,0, picWidth, picHeight);
imageData = ctx.getImageData(newX,newY, canvas.width, canvas.height);
originalCopy = ctx.getImageData(newX,newY, picWidth, picHeight);
data = imageData.data;
function resize(val){ Resizes picture
userPicHeight = document.getElementById("cSelect").value;
userPicWidth = document.getElementById("cSelect").value;
ctx.clearRect(0,0, canvas.width, canvas.height);
ctx.drawImage(imgObj, newX, newY, userPicWidth, userPicHeight);
window['imageData'] = ctx.getImageData(newX,newY, userPicWidth, userPicHeight);
ctx.putImageData(imageData, newX, newY);
};
imageData is a snapshot of canvas pixel data. In your case it's the entire canvas's (colored--not B&W) pixel data.
So when you do .putImageData(imageData...) the unaltered snapshow is again displayed on the canvas.
If you want to rescale a B&W version of your picture:
Draw your color image on a new canvas created with var memCanvas = document.createElement. Size the canvas to the image size. The canvas can be left in-memory -- no need to appendChild it into the DOM.
Apply the filter to the new canvas with getImageData, modify pixel data, putImageData. Now you have an "image-canvas" that you can later use to resize, etc.
Draw the image-Canvas onto the visible canvas: context.drawImage(memCanvas,0,0). Yes, the memCanvas can be an image source for drawImage.
To scale the B&W version of the image, just clear the canvas, scale the canvas with context.scale & then draw the scaled B&W image with drawImage(memCanvas,0,0)
If you later want to re-rescale the B&W image, you can do Step#4 again.
Example code and a Demo using a grayscale filter:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/kingcard.png";
function start(){
// create a grayscale image-canvas
var grayImg=makeFilteredImageCanvas(img,grayscaleFilter);
// scale the visible canvas
ctx.scale(1.25,1.25);
// draw the grayscale imag-canvas on the canvas
// (the result will be scaled)
ctx.drawImage(grayImg,0,0);
}
function makeFilteredImageCanvas(img,filter){
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
iw=c.width=img.width;
ih=c.height=img.height;
cctx.drawImage(img,0,0);
filter(cctx);
return(c);
}
function grayscaleFilter(context){
var canvas=context.canvas;
var w=canvas.width;
var h=canvas.height;
var imageData=context.getImageData(0,0,w,h);
var data=imageData.data;
for(var i=0;i<data.length;i+=4){
var gray=data[i]*0.33+data[i+1]*0.5+data[i+2]*0.16;
data[i]=data[i+1]=data[i+2]=gray;
}
context.putImageData(imageData,0,0);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<h4>Grayscale image scaled up by 25%</h4>
<canvas id="canvas" width=300 height=300></canvas>
<h4>Original Image:</h4>
<img src='https://dl.dropboxusercontent.com/u/139992952/multple/kingcard.png' crossOrigin='anonymous'>
I've watched a bunch of tutorials and am currently trying to cut the top right piece out, but can only cut in a straight line. Not I'm stuck wondering how I would go by to cut remaining tilted line on this piece. How would I go by doing that?
This is the line I'm talking about: http://imgur.com/GgxPcb0
The fiddle: http://jsfiddle.net/8b1a64pm/2/
<body>
<canvas id="NewCanvas" height="800" width="800">
</canvas>
</body>
And the javascript
var can=document.getElementById("NewCanvas");
var Jctx=can.getContext("2d");
var img = new Image();
img.onload = function() {
Jctx.drawImage(img,150,10);
//drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);
Jctx.drawImage(img,150, 45, 150, 100, 100, 300, 150, 100);
}
img.src='http://images.sodahead.com/polls/004087283/3238285773_0912_holiday_pie_slicespreview_answer_103_xlarge.jpeg';
Use the clip method on the new canvas to cut out only part of the original.
Eg
// ctx is the new canvas
ctx.save(); // save the current state
ctx.moveTo(0,0);
ctx.lineTo(150,0);
ctx.lineTo(75,150);
ctx.closePath();
ctx.clip();
ctx.drawImage(img,0,0); // new image is clipped
ctx.restore(); // revert to old state and removes the clip.
I can make a obj to use the canvas to draw like this:
MyObj.myDiv = new Canvas($("effectDiv"), Setting.width, Setting.height);
Then, I use this to draw a rectangle on the canvas:
var c = new Rectangle(80, 80,
{
fill: [220, 40, 90]
}
);
var move = new Timeline;
move.addKeyframe(0,
{
x: 0,
y: 0
}
);
c.addTimeline(move);
MyObj.myDiv.append(c);
But after I draw the rectangle, I want clear the canvas, but I don't know which method and how to do this... ...
O...one more thing:
it is the CAKE's web site:
Link
Clearing the canvas:
canvas.clear = true; // makes the canvas clear itself on every frame
canvas.fill = somecolor; // fills the canvas with some color on every frame
// with canvas.clear = false and low-opacity fill, fancy motion blur effect
Removing the rectangle from the canvas:
rectangle.removeSelf();
or
canvas.removeChild(rectangle);
You can try this method:
MyObj.myDiv.clearRect(0, 0, canvas.width, canvas.height);
Which effectively colours the entire canvas in the background colour.
Easiest way is:
MyObj.myDiv.width = MyObj.myDiv.width;
I found that resizing the canvas works like magic, even if you're not really changing the size:
canvas.width = canvas.width