I want to get a .jpg on a canvas, add a rectangle and a String, which is working very good. After that I want to create a jpg out of the canvas, which works fine but the jpg of the canvas does only show the rectangle and the String. Quick Code-example - i know its a ugly canvas - just testing ;)
<!DOCTYPE html>
<html>
<body>
<canvas id="meinCanvas" width="600" height="600" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body>
<script type="text/javascript">
var canv = document.getElementById("meinCanvas");
var context = canv.getContext("2d");
context.fillStyle = "#000000";
context.fillRect(10,10, 200, 100);
var img = new Image();
img.onload = function() {
context.drawImage(img, 300, 300);
};
img.src="one.jpg";
context.font = "bold 12px sans-serif";
context.fillText("test", 500, 500);
imgsr = canv.toDataURL("image/jpeg");
document.write('<img src="' +imgsr +'"/>');
</script>
</html>
}
In the upper part (the canvas) the img is shown properly, but in the .jpeg beneth it the img is not shown. Help would be great. thanks.
Image is not loaded yet when you save it.
Put the toDataUrl in img.onload or link it to an event or timer
Related
Two canvases one on top of the other as below. The second canvas cvs should be transparent since by default all canvases are transparent and I do a clearRect just to make sure.
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<canvas id="myCanvas" width="578" height="430"></canvas>
<canvas id="cvscan" style="display:none"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var cvs = document.getElementById('cvscan');
var cvsctx = cvs.getContext('2d');
context.save();
context.clearRect(0, 0, 578, 430);
context.fillStyle = 'gray';
context.fillRect(0, 0, 578, 430);
context.beginPath();
context.moveTo(0, 0);
context.lineWidth = 3;
context.lineTo(578, 430);
context.strokeStyle = '#444444';
context.stroke();
context.moveTo(578, 0);
context.lineTo(0, 430);
context.stroke();
cvs.width = 200;
cvs.height = 200;
cvsctx.clearRect(0, 0, cvscan.width, cvscan.height);
var curimg = cvsctx.getImageData(0, 0, cvs.width, cvs.height);
context.putImageData(curimg, 50, 50);
context.restore();
</script>
</body>
</html>
I believe the second canvas should be transparent and (since there's nothing drawn in it) invisible -- but it's filled with white. What am I missing?
UPDATE this is what I see -- I believe the white box should not be there.
Here is the image
The canvas with id="cvscan" is being cleared, which means the image data is being set to 0 for all, rgba(0,0,0,0), values.
Next, that image data is being painted onto the canvas with id="myCanvas", updating the pixel on "myCanvas" to zero.
So, the canvas ("myCanvas") is now transparent at the painted location, and is seen as white, because the background of the body is now showing.
To validate the results a test was run logging the data of the image, and then updating bgcolor to red.
(see photos)
I am trying to convert an image to another color using kineticjs, actually my image will be on a layer and also a png one can i change only the image objects color? any help will be very greatful
You can replace non-transparent pixels with a new color using compositing.
In particular source-atop compositing will replace all existing non-transparent pixels with any color you draw.
KineticJS does not currently offer compositing out-of-the-box, but you can easily use an html5 Canvas element to do the compositing and then use that element as an image source for a Kinetic.Image element.
Here's example code and a Demo:
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 350
});
var layer = new Kinetic.Layer();
stage.add(layer);
var canvas=document.createElement('canvas');
var ctx=canvas.getContext('2d');
var kImage;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/flower.png";
function start(){
cw=canvas.width=img.width;
ch=canvas.height=img.height;
ctx.drawImage(img,0,0);
kImage=new Kinetic.Image({
image:canvas,
width:img.width,
height:img.height,
draggable:true,
});
layer.add(kImage);
layer.draw();
document.getElementById('makeGreen').onclick=function(){
ctx.globalCompositeOperation='source-atop';
ctx.fillStyle='lightgreen';
ctx.fillRect(0,0,cw,ch);
layer.draw();
};
document.getElementById('makeOriginal').onclick=function(){
ctx.globalCompositeOperation='source-over';
ctx.drawImage(img,0,0);
layer.draw();
};
}
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:350px;
}
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.1.0.min.js"></script>
<button id=makeGreen>Green</button>
<button id=makeOriginal>Original</button>
<div id="container"></div>
Is it possible to move an image behind a mask without moving the mask itself ? I am looking for an operation which allow to move an image behind a mask and it should be accurate and smooth.
The best answer I am looking is to mask an Kinetic.Image object. Kinetic.Image is draggable and need to worry about it's movement. Please let me know if it's really possible to mask Kinetic.Image Object ?
A Demo: http://jsfiddle.net/m1erickson/u28MS/
Use a Kinetic.Shape to get access to the canvas context and then create a clipping region.
Create a new Kinetic.Shape
Define your non-rectangular path in the shape
Call clip() to restrict drawing to that path.
Draw the image into the clipping region.
Give the image x & y properties so that the image can be draw
Here's what that looks like in code:
// create a Kinetic.Shape which gives you access
// to a context to draw on
clippingShape = new Kinetic.Shape({
sceneFunc: function(context) {
// define your path here
// context.beginPath(); ...
// make your path a clipping region
context.clip();
// draw the image inside the clipping region
// img.x & img.y are offsets which can be used
// to "drag" the image around the clipping region
context.drawImage(img,img.x,img.y);
// KineticJS specific context method
context.fillStrokeShape(this);
},
stroke: 'black',
strokeWidth: 4,
listening:false
});
Listen for mouse events on the stage to cause the image to reposition when drawn in the Shape.
In mousedown: Save the mouse position and set a flag indicating the drag has begun.
In mousemove: Calc how much the mouse has moved and offset the image's x/y by that distance.
In mouseup: clear the dragging flag since the drag is over.
The mouse event handlers look like this:
var isdown=false;
stage.getContent().onmousedown=function(e){
var pos=stage.getPointerPosition();
img.lastX=parseInt(pos.x);
img.lastY=parseInt(pos.y);
isdown=true;
};
stage.getContent().onmouseup=function(e){
isdown=false;
};
stage.getContent().onmousemove=function(e){
if(!isdown){return;}
var pos=stage.getPointerPosition();
var mouseX=parseInt(pos.x);
var mouseY=parseInt(pos.y);
var dx=mouseX-img.lastX;
var dy=mouseY-img.lastY;
img.lastX=mouseX;
img.lastY=mouseY;
img.x+=dx;
img.y+=dy;
layer.draw();
};
[ Previous version of answer -- replaced with new answer above after questioners commments ]
This kind of clipping is traditionally done with a foreground image that contains a transparent "viewport" which lets the user see a portion of the background image beneath.
A Demo: http://jsfiddle.net/m1erickson/2f9yu/
Create a draggable background image on a bottom layer:
// create a background layer
var bottomLayer=new Kinetic.Layer();
stage.add(bottomLayer);
// put a draggable image on the background layer
var city=new Kinetic.Image({ image:bk,x:0,y:0,draggable:true,width:700,height:440, });
bottomLayer.add(city);
bottomLayer.draw();
Create a non-draggable foreground image on a top layer.
The top image has a transparent "viewport".
Important: the top layer does not listen for events, so dragging moves the bottom image, not the top image.
// create a top layer that does not respond to mouse events
// any mouse events will filter down to the background image
// this enables the background to be dragged even while behind the top image
var topLayer=new Kinetic.Layer({listening:false,});
stage.add(topLayer);
// create a top image with transparent pixels
// used as a viewport to see a portion of the bottom image
var mirror=new Kinetic.Image({ image:viewport,x:0,y:0 });
topLayer.add(mirror);
topLayer.draw();
Example code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v5.0.1.min.js"></script>
<style>
body{padding:20px;}
#container{
border:solid 1px #ccc;
margin-top: 10px;
width:350px;
height:300px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 350,
height: 300
});
var layer = new Kinetic.Layer();
stage.add(layer);
var bottomLayer=new Kinetic.Layer();
stage.add(bottomLayer);
var topLayer=new Kinetic.Layer({listening:false,});
stage.add(topLayer);
var loadedCount=0;
//
var bk=new Image();
bk.onload=start;
bk.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/desert1.jpg";
//
var viewport=new Image();
viewport.onload=start;
viewport.src="https://dl.dropboxusercontent.com/u/139992952/multple/car4.png";
function start(){
if(++loadedCount<2){return;}
var city=new Kinetic.Image({ image:bk,x:0,y:0,draggable:true,width:700,height:440, });
bottomLayer.add(city);
bottomLayer.draw();
var mirror=new Kinetic.Image({ image:viewport,x:0,y:0 });
topLayer.add(mirror);
topLayer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag to move the background image in the mirror</h4>
<div id="container"></div>
</body>
</html>
Improve HTML5 Canvas frame by frame JPG animation to fully cache before animating
The above code snippet is great. I'd like to be able to apply new widths with css/media queries to the canvas that holds the jpgs. Is there a way to add that to the above code?
when I tried it my jpg's became wildly oversized.
It appears in the above code that the height and width declared in js for the image and the height and width on the canvas tag need to match or things get wonky.
I want to dynamically call the image width with CSS and media queries.
thanks
<style type="text/css">
/*CSS for full screen animation.You may want to remove this*/
html,body {
height:100%;
width:100%;
padding:0;
margin:0;
}
/*ID for Canvas JPG Animation - Sets size, background image and loader*/
#anim {
background-image:url('images/icon_loading_75x75.gif'),url('images/t5.png');
/*Center=Loading GIF, Left Top= Placeholder Image*/
background-position: center, left top;
background-repeat: no-repeat;
height:500px;
width:660px;
}
</style>
<script type="text/javascript">
function draw() {
var ctx = document.getElementById('anim').getContext("2d");
var start = 1, stop = 121,cur=start,imgArr=[];
//Pre-loads Images
var loadLoop = function() {
var img = document.createElement("img");
img.onload = function() {
imgArr.push(this);
cur++;
if(cur > stop) {
// all images preloaded
animate();
}
else {
loadLoop();
}
}
//img.src = "jpg_80/t5_"+(cur)+".jpg";
img.src = "http://html5canvas.syntheticmedia.net/jpg_80/t5_"+(cur)+".jpg";
//jpg_80/t5_88.jpg
}
loadLoop();
//Canvas JPG Animation
function animate() {
var timer = setInterval(function() {
ctx.drawImage(imgArr.shift(), 0, 0 );
if(imgArr.length == 0) {
// no more frames
clearInterval(timer);
}
//Framerate # 24 Frames per Second
},1000/24);
}
}
</script>
<script src="modernizr-2.6.2.min.js" type="text/javascript">
</script>
<body>
<!-- HTML5 Canvas Animation-->
<canvas id="anim" width="660" height="500"></canvas>
<script>
//call after page loaded
window.onload = draw;
</script>
</body>
Here's my example: http://jsbin.com/urofan/7/edit
I would like to draw the video into a custom shape, not in a rectangle shape, is that possible right now? (PS: The shape is draggable) All I found in StackO or in the web are for rectangular drawings...
In the future, the shape will be a circle with adjustable radius and position (draggable and resizable).
Thanks for your help.
Allan.
You can contain an image (video frame grab) into a path using the clip method.
First define the path you want the video frame to be contained in.
Note that you don’t have to do fill/stroke.
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.lineTo(250, 400);
context.lineTo(40, 80);
context.closePath();
Next, create a clipping path from your defined path.
Everything drawn after this will be clipped inside your clipping path.
context.clip();
Finally, draw a frame grab of the video and drawImage into the clipping path.
The frame grab will only appear inside your clipping path.
context.drawImage(0,0,canvas.width,canvas.height);
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/aMW74/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Prototype</title>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<script src="http://d3lp1msu2r81bx.cloudfront.net/kjs/js/lib/kinetic-v4.5.1.min.js"></script>
<style>
#container{
border:solid 1px #ccc;
margin-top: 10px;
}
</style>
<script>
$(function(){
var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500
});
var layer = new Kinetic.Layer();
stage.add(layer);
var img=document.createElement("img");
img.onload=function(){
drawClippedImage(img);
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/KoolAidMan.png";
function drawPathForClipping(context){
context.beginPath();
context.moveTo(200, 50);
context.lineTo(420, 80);
context.lineTo(250, 400);
context.lineTo(40, 80);
context.closePath();
}
function drawClippedImage(img){
var shape = new Kinetic.Shape({
id: 'shape',
drawFunc: function(canvas) {
var context = canvas.getContext();
// define the path that will be used for clipping
drawPathForClipping(context);
// make the last path a clipping path
context.clip();
// draw a clipped image (frame grab)
context.drawImage(img,0,0,img.width,img.height);
// styling, draw the clip path for real as a border
drawPathForClipping(context);
canvas.stroke(this);
},
stroke: 'black',
strokeWidth: 4,
draggable: true
});
// add the shape shape to the layer
layer.add(shape);
layer.draw();
}
}); // end $(function(){});
</script>
</head>
<body>
<div id="container"></div>
</body>
</html>