fill transparent png on canvas - javascript

I have the following question for filling up a transparent “png” image on a canvas. Filling up a circle/rectangle works like a charm. When I replace the circle or rectangle by a png, then it doesn’t fill as I want. Here’s the code.
When I replace the line "context.arc...." by the line "context.drawimage....." the png is shown on the canvas , but the fill doesn't work.
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var ThumbImg = document.createElement('image');
var MyShape = document.createElement('image');
ThumbImg.src = 'stof2.jpg';
MyShape.src = 'Myshape.png';
//-----begin custom shape-----
context.arc(100,100, 100, 0, Math.PI*2,true);
//context.drawImage(MyShape, 100, 0, 300,300);
//-----End custom shape-----
//---Start Fill custom Image------
context.fillStyle = context.createPattern(ThumbImg ,'no-repeat')
context.fill();
//---End Fill custom Image------
</script>

Related

trying to colorize a simple PNG and draw inside a mask element in canvas

I tried to create an HTML canvas, place a rectangle... then INSIDE THAT rectangle, draw various shapes and an RGBa PNG... all of them clipped inside the dimensions of the rectangle. Then I tried to change the color of the PNG when you press an HTML button input. (Further comments in code.)
Heres the problems... A. You have to draw to a temporary canvas and apply "GlobalCompositeOperation source-atop" just AFTER the clipping rectangle. Everything drawn after that is successfully clipped into the rect shape. Then the whole thing is copied (drawn) to a MAIN canvas. I was told to do it this way in order for the programming to recognize MULTIPLE elements after a "composite" operation. I have to say this works BEAUTIFULLY!! but here's problem B...
To to a "getData" on an image (to change color), I think you have to place the image on a canvas, and doing all the image pixel manipulation screws up the "composite" operation, so I tried to draw the PNG to a THIRD canvas, do the pixel changes, and then draw it to the temporary canvas... adding it to the rest of the elements....THEEENNN draw it all to the main canvas. Does not work. See code. Please help, Im mad enough to chew neutronium.
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<canvas id="theCanvas" width="200" height="200" style="border:2px solid #000000;"></canvas>
<canvas id="tempCanvas" width="200" height="200" style="display:none;"></canvas>
<canvas id="anotherCanvas" width="200" height="200" style="display:none;"></canvas>
<form>
<input type="button" id="changeColor" value="Click to Change Color of Graphic">
</form>
<script type="text/javascript" src="hereWeGoAgain_GHELP.js"></script>
</body>
</html>
//------------------------------------- JS
window.addEventListener("load", eventWindowLoaded, false);
function eventWindowLoaded () {
canvasApp();
}
function canvasApp() {
var canvas = document.getElementById('theCanvas');// the main canvas, where it all goes in the end
var context = canvas.getContext('2d');
var tempCanvas = document.getElementById('tempCanvas');// the canvas to do my "source-atop" stuff...
var tempContext = tempCanvas.getContext('2d');
var anotherCanvas = document.getElementById('anotherCanvas');
var anotherContext = anotherCanvas.getContext('2d');
// ...and Im thinking I should draw the RGBA PNG here, before placing it in the temp canvas, with the other elements
var cc = document.getElementById('changeColor');
cc.addEventListener('click', function(){changeColorFunction('ff0000');}, false);
// the HTML form button to change the PNG color
var colorOfThePlacedPNG = "#000000";
var imagesToLoad = 0;
var imagesLoaded = 0;
function drawScreen() {
tempContext.fillStyle="#999999";
tempContext.fillRect(0,0,200,200); //color the whole temp canvas area grey....
tempContext.fillStyle="#2baae1";
tempContext.fillRect(30,30,140,140);//now draw a light blue rect inside....
tempContext.globalCompositeOperation="source-atop"; // now make everything drawn AFTERWARDS be clipped (masked) inside the blue rect
// when I comment out the above "global Comp Op"... everything draws to the main canvas normally...just not clipped(masked) however
tempContext.fillStyle="#f47e1f";
tempContext.fillRect(150,100,150,150);//SO heres an orange box intentionally clipped off the bottom right in the blue rect
tempContext.fillStyle="#d89bc5";
tempContext.fillRect(40,50,80,200);//AND heres a light purple rect intentionally clipped at the bottom of the blue rect
getTheImageData(); //draw PNG to another canvas, convert image data, put in tempContext
//tempContext.restore();//dont know if I need this
context.drawImage(tempCanvas, 0, 0);// and then FINALLY draw all to the main canvas
}
var loaded = function(){
imagesLoaded += 1;
if(imagesLoaded === imagesToLoad){
drawScreen();
}
}
var loadImage = function(url){
var image = new Image();
image.addEventListener("load",loaded);
imagesToLoad += 1;
image.src = url;
return image;
}
function changeColorFunction(e) {
colorOfThePlacedPNG = e;
drawScreen();
}
function getTheImageData(){
anotherContext.drawImage(testPNGimage, 0, 0);// draw to the third canvas(another canvas)
var imgData = anotherContext.getImageData(0, 0, 200, 200);
// how do i color it red? ....like #ff0000 ???
var i;
for (i = 0; i < imgData.data.length; i += 4) {
imgData.data[i] = 255 - imgData.data[i];
imgData.data[i+1] = 255 - imgData.data[i+1];
imgData.data[i+2] = 255 - imgData.data[i+2];
imgData.data[i+3] = 255;
}
tempContext.putImageData(imgData, 0, 0);
}
var testPNGimage = loadImage("test.png");// the PNG is just a 75X75px black squiggle drawn in pshop
}
You're overcomplicating things!
There is a clipping method built into canvas.
Use clipping instead of compositing and multiple canvases.
Do this and all new drawings will be clipped inside your 140x140 rect:
context.beginPath();
context.rect(30,30,140,140);
context.clip();
Here's a simplified redesign of your code:
Draw a grey rect filling the canvas.
Draw a blue 140x140 rect at [30,30].
Clip all new drawings into the blue rect with context.clip()
Draw a clipped orange rect.
Draw a clipped purple rect.
Unclip so new drawings will be visible anywhere on the canvas.
Draw the squiggle image (it's not clipped).
Use .getImageData to invert every pixel's color.
And a Demo:
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/squiggle.png";
function start(){
//color the whole canvas area grey....
ctx.fillStyle="#999999";
ctx.fillRect(0,0,200,200);
//now draw a light blue rect inside....
ctx.fillStyle="#2baae1";
ctx.beginPath();
ctx.rect(30,30,140,140);
ctx.fill();
// save the unclipped context state
ctx.save();
// cause all new drawings to be clipped inside
// the blue 140x140 rect at [30,30]
ctx.clip();
//SO heres an orange box intentionally clipped off the bottom right in the blue rect
ctx.fillStyle="#f47e1f";
ctx.fillRect(150,100,150,150);
//AND heres a light purple rect intentionally clipped at the bottom of the blue rect
ctx.fillStyle="#d89bc5";
ctx.fillRect(40,50,80,200);
// restore the context state (releases clipping for new drawings)
ctx.restore();
// draw the squiggley line image -- it's not clipped in the blue rect
ctx.drawImage(img,0,0);
// invert the colors using getImageData
var imgData = ctx.getImageData(0, 0, 200, 200);
var i;
for (i = 0; i < imgData.data.length; i += 4) {
imgData.data[i] = 255 - imgData.data[i];
imgData.data[i+1] = 255 - imgData.data[i+1];
imgData.data[i+2] = 255 - imgData.data[i+2];
imgData.data[i+3] = 255;
}
ctx.putImageData(imgData, 0, 0);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=200 height=200></canvas>

assign canvas to div, adapt canvas dimensions to div dimenson - how to fix?

I have this example of a canvas as a div background (I forked it from another example, don't remember where I found it):
http://jsfiddle.net/sevku/6jace59t/18/
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var divHeight = document.getElementById('canvas').clientHeight;
var divWidth = document.getElementById('canvas').clientWidth;
function assignToDiv(){ // this kind of function you are looking for
dataUrl = canvas.toDataURL();
document.getElementsByTagName('div')[0].style.background='url('+dataUrl+')'
}
function draw() { // replace with your logic
ctx.fillStyle = "rgb(100, 250, 100)";
ctx.fillRect (10, 10, divWidth-20, divHeight-20);
}
draw()
assignToDiv()
My problem; If I put the dimensions of the div 300 x 150, the canvas does what it is supposed to do. But if I change the dimensions, the canvas is supposed to adapt to the div dimensions. What did I do wrong that this doesn't happen?
PS: I'm a beginner, so please forgive me stupid questions.
It's because if you don't give canvas width and height, it's default to 300x150, so after you get the width and height from div, you should use them to set your canvas' dimensions as well.
Another point worth notice is that you use div.style.background property to set the background image, however, as there's many background related properties (e.g: background-repeat in your jsfiddle, background-position, background-size...), the background can set all of them at once.
When you use div.style.background='url('+dataUrl+')';. It overrides all other background-related properties to initial.
If you want to preserve those properties, you may either reset them after you set style.background, or you can use div.style.backgroundImage to change the background image without affect other background related properties.
jsfiddle
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var divHeight = document.getElementById('canvas').clientHeight;
var divWidth = document.getElementById('canvas').clientWidth;
// VVVV After you get WxH, set the canvas's dimension too.
canvas.width = divWidth;
canvas.height = divWidth;
var div1 = document.getElementById('canvas');
var div2 = document.getElementById('canvas2');
function assignToDiv(div){ // this kind of function you are looking for
var dataUrl = canvas.toDataURL();
div.style.background='url('+dataUrl+')'; // This line will overwrite your background settings.
div.style.backgroundRepeat = 'repeat-x'; // Use this to set background related properties after above.
}
function assignToDivAlt(div){ // this kind of function you are looking for
var dataUrl = canvas.toDataURL();
div.style.backgroundImage = 'url('+dataUrl+')'; // Only set the background-image would have same effect.
}
function draw() { // replace with your logic
ctx.fillStyle = "rgb(100, 250, 100)";
// If you don't set WH, then the canvas would be 300x150, and those
// you drawed but out of boundary are clipped.
ctx.fillRect (10, 10, divWidth-20, divHeight-20);
}
draw()
assignToDiv(div1);
assignToDiv(div2);
canvas {display:none;}
div {
width:600px;
height:550px;
border:1px solid grey;
background-repeat:repeat-x;
}
<canvas></canvas>
<div id="canvas"></div>
<div id="canvas2"></div>

How can I manipulate the slices of an image separately using canvas?

I am new to the "canvas" term in HTML. I sliced a picture in 2 halves, leaving a small gap between them. I want to rotate each half separately to create a half folding effect.
window.onload = function () {
var myCanv = document.getElementById("myCanvas");
var context = myCanv.getContext('2d');
var myImage = document.getElementById("myImage");
context.drawImage(myImage, 0, 0, myImage.width / 2, myImage.height, 0, 0, myCanv.width / 2, myCanv.height);
context.drawImage(myImage, (myImage.width / 2) + 1, 0, myImage.width / 2, myImage.height, (myCanv.width / 2) + 0.5, 0, myCanv.width / 2, myCanv.height);
};
Is there any way that I can do this using canvas? I appreciate any help. :)
Here is a fiddle. I know it's not much but any hint is useful.
You probably want to skew the 2 halves of the image rather than rotate them.
To skew you can use context.transform or context.setTransform.
Example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var skewLeft=.1;
var skewRight=-.1;
var cx=100;
var y=30;
var iw,ih;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/cars.jpg";
function start(){
iw=img.width;
ih=img.height;
draw();
}
function draw(){
// fill the canvas background with gray
ctx.fillStyle='gray';
ctx.fillRect(0,0,cw,ch);
ctx.fillStyle='black'
// draw the left skewed page with a stroked border
ctx.setTransform(1,skewLeft,0,1,cx,0);
ctx.drawImage(img,0,0,iw/2,ih,-iw/2,y,iw/2,ih);
ctx.strokeRect(-iw/2,y,iw/2,ih);
ctx.setTransform(1,0,0,1,0,0);
// draw the right skewed page with a stroked border
ctx.setTransform(1,skewRight,0,1,cx,0);
ctx.drawImage(img,iw/2,0,iw/2,ih,0,y,iw/2,ih);
ctx.strokeRect(0,y,iw/2,ih);
ctx.setTransform(1,0,0,1,0,0);
}
body{ background-color:white; }
img,#canvas{border:1px solid red;}
<h4>Original Image (left) and<br>Image halved, skewed & bordered to look like a fold</h4>
<img src='https://dl.dropboxusercontent.com/u/139992952/multple/cars.jpg'>
<canvas id="canvas" width=225 height=150></canvas>

Copy Canvas Image into a Frame

As starting point I have a image on my canvas:
var canvas = $('canvas')[0];
var ctx=canvas.getContext("2d");
var img=document.getElementById("scream");
ctx.drawImage(img,0,0,240,297);
Now I would like to add a frame to this Image on the same canvas. For this:
I first replace the image with the Frame.
Next I try to copy the old canvas content inside of this frame
I try to do this like that:
var frame = document.getElementById("frame");
var ctx = $('canvas')[0].getContext("2d");
var dst = ctx.canvas;
ctx.drawImage(frame,0,0, 240, 297);
ctx.drawImage(dst, 40, 40);
But the code is not working because it copies the frame again to the canvas instead of the image: Here you can see a demo: https://jsfiddle.net/35mxfsv0/
What do I wrong? What do I have to change? Thanks
As you just assign the original canvas to dst, when you draw anything on that canvas, the dst will also changed (because they're pointing to same canvas).
So you have to assign a new canvas to dst, and draw the image from origin to dst, then draw the frame on origin, and last, draw dst's image to origin.
window.onload = function() { // Make it safe that window.onload ensures all images loaded.
var canvas = $('canvas')[0];
var ctx=canvas.getContext("2d");
var img=document.getElementById("scream");
ctx.drawImage(img,0,0,240,297);
//START OF MY CODE
var frame = document.getElementById("frame");
// Comment out as we demo in same scope, ctx is already have what we want.
//var ctx = $('canvas')[0].getContext("2d");
// Create a new canvas, and draw the image on the origin canvas to it.
var dst = document.createElement('canvas');
dst.width = canvas.width;
dst.height = canvas.height;
var dstCtx = dst.getContext('2d');
dstCtx.drawImage(canvas, 0, 0);
// Above is what you suppose the canvas should do.
//var dst = ctx.canvas;
// Draw frame
ctx.drawImage(frame,0,0, 240, 297);
// As your frame is not an opacity one, you have to copy to specific position.
ctx.drawImage(dst, 0, 0, dst.width, dst.height, 10, 10, 220, 277);
}
img{display:none}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<canvas id="myCanvas" width="240" height="297" style="border:1px solid #d3d3d3;">
</canvas>
<img src="http://www.w3schools.com/tags/img_the_scream.jpg" id="scream"/>
<img src="http://www.wpclipart.com/page_frames/picture_frames/wood_picture_frame.jpg" id="frame"/>
However, if you still have the access to that scream image, you can just draw frame first, then draw image on it:
var canvas = $('canvas')[0];
var ctx=canvas.getContext("2d");
var img=document.getElementById("scream");
var frame = document.getElementById("frame");
ctx.drawImage(frame,0,0, 240, 297);
// 10, 10 seems to fit the frame.
ctx.drawImage(img, 10, 10);
Please change id of your html and js file.

Save Canvas with Background Image

I have a background image for a canvas, and added a few basic elements to the canvas. Now I want to save the canvas (in .png), with the background image of the canvas style.
Tried:
var canvas = document.getElementById("mycanvas");
var img = canvas.toDataURL("image/png");
But this doesn't seem to save the background image of the canvas. Is there a way out?
When you want to save the Canvas + background as an image, you will need to do a sequence of events:
Create an in-memory canvas just as big as your normal canvas. Call it can2
ctx2.drawImage(can1, 0, 0) // paint first canvas onto new canvas
ctx.clearRect(0, 0, width, height) // clear first canvas
ctx.drawImage(background, 0, 0) // draw image on first canvas
ctx.drawImage(can2, 0, 0) // draw the (saved) first canvas back to itself
To save an image location, I believe your looking for:
window.location = canvas.canvas.toDataURL('image/png');
The first canvas call is your variable the second is the canvas object.
You should probably rename your variable to something unique.
To set an image in canvas and make that the background requires some more work:
var myCanvas = document.querySelector('myCanvas'),
img = document.createElement('img'),
ctx = myCanvas.getContext ? myCanvas.getContext('2d') : null;
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
img.onload = function () {
ctx.drawImage(img, 0, 0, myCanvas.width, myCanvas.height);
};
img.src = 'image.png';
updated to redraw the image.

Categories