Using destination-over to save background and actual sketch - javascript

I've read this and a few other questions, and it is clear I need to use destination-over to save the background and the sketch by display the new image over the old one.
I'm using Sketch.JS with my code as such:
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
$('#myCanvas').sketch({
defaultColor: "red"
});
$('#download').click(function() {
ctx.globalCompositeOperation = "destination-over";
img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = 'http://lorempixel.com/400/200/';
ctx.drawImage(img, 0, 0);
$('#url').text(c.toDataURL('/image/png'));
window.open(c.toDataURL('/image/png'));
});
#myCanvas {
background: url(http://lorempixel.com/400/200/);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/intridea/sketch.js/gh-pages/lib/sketch.js"></script>
<canvas id="myCanvas"></canvas>
<input type='button' id='download' value='download'>
<span id='url'></span>
Fiddle
But that doesn't help. Clicking 'download' still only produces the sketch. Now, it seems I don't understand how I need to use destination-over properly. W3Schools doesn't seem to help.
Could anyone point me in the right direction please?

Assume you have a SketchJS canvas on top of an image containing a background:
#wrapper{positon:relative;}
#bk,#myCanvas{position:absolute;}
<div id='wrapper'>
<img crossOrigin='anonymous' id=bk src='yourImage.png'>
<canvas id="myCanvas" width=500 height=300></canvas>
</div>
Then when you want to combine the Sketch with the background and save it as an image you can use destination-over compositing to draw the background "under" the existing Sketch.
ctx.globalCompositeOperation='destination-over';
ctx.drawImage(bk, 0, 0);
Here's example code:
<!doctype html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://rawgit.com/intridea/sketch.js/gh-pages/lib/sketch.js"></script>
<style>
body{ background-color: ivory; }
#wrapper{positon:relative;}
#bk,#myCanvas{position:absolute;}
</style>
<script>
$(function(){
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
$('#myCanvas').sketch({ defaultColor: "red" });
$('#download').click(function() {
var img=document.getElementById('bk');
ctx.globalCompositeOperation='destination-over';
ctx.drawImage(bk, 0, 0);
ctx.globalCompositeOperation='source-over';
var html="<p>Right-click on image below and Save-Picture-As</p>";
html+="<img src='"+c.toDataURL()+"' alt='from canvas'/>";
var tab=window.open();
tab.document.write(html);
});
}); // end $(function(){});
</script>
</head>
<body>
<h4>Drag to sketch on the map.</h4>
<button id=download>Download</button>
<div id='wrapper'>
<img crossOrigin='anonymous' id=bk src='https://dl.dropboxusercontent.com/u/139992952/multple/googlemap1.png'>
<canvas id="myCanvas" width=459 height=459></canvas>
</div>
</body>
</html>

Related

closePath() Moving Polygon

The following code below is what is needed to make a simple triangle. I want to keep the triangle in that exact position and add this to my canvas.
can = document.getElementById("gameCanvas");
var ctx = can.getContext("2d");
ctx.beginPath();
ctx.moveTo(1, 20);
ctx.lineTo(20, 100);
ctx.lineTo(70, 100);
ctx.closePath();
ctx.stroke();
If you run the code below, the triangle is there for a split second and then disappears. I need it to stay there along with the three equations. I created the function path(); in effort to keep the triangle positioned in the upper left corner. I am not sure how to keep the triangle there and do all of this.
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="text/javascript" src="//code.createjs.com/createjs-2013.09.25.combined.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
#gameCanvas {
background-color: lightyellow;
}
</style>
<div class="canvasHolder1">
<div id="eqn1"> 3+3=<input type="text" id="q1" />
</div>
<div id="eqn2"> 3+2=<input type="text" id="q2" />
</div>
<div id="eqn3"> 5+2=<input type="text" id="q3" />
</div>
<canvas id="gameCanvas" width="600" height="600">Not supported</canvas>
<script type="text/javascript">
var m=1;
var stage = new createjs.Stage("gameCanvas");
var obj=[];
can = document.getElementById("gameCanvas");
var ctx = can.getContext("2d");
ctx.beginPath();
ctx.moveTo(1, 20);
ctx.lineTo(20, 100);
ctx.lineTo(70, 100);
ctx.closePath();
ctx.stroke();
function startGame() {
obj[1] = new createjs.DOMElement(document.getElementById(`eqn${1}`));
obj[2] = new createjs.DOMElement(document.getElementById(`eqn${2}`));
stage.addChild(obj[1]);
stage.addChild(obj[2]);
createjs.Ticker.addEventListener("tick", handleTick);
createjs.Ticker.setFPS(60);
function handleTick(event){
drop(1);
drop(2);
path();
stage.update();
}
}
function drop(i){
obj[1].x =40;
obj[1].y =50;
obj[2].x =300;
obj[2].y =50;
}
function path(){
ctx.x=1;
ctx.y=1;
}
</script>
<body onload="startGame();">
<div >
<canvas>This browser or document mode doesn't support canvas object.</canvas>
</div>
</body>
</html>
Take a look at this:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Math Game</title>
<script src="//code.createjs.com/createjs-2013.09.25.combined.js"></script>
</head>
<body onload="startGame();">
<div class="canvasHolder1">
<div id="eqn1"> 3+3=<input type="text" id="q1" /></div>
<div id="eqn2"> 3+2=<input type="text" id="q2" /></div>
<div id="eqn3"> 5+2=<input type="text" id="q3" /></div>
<canvas id="gameCanvas" width="600" height="200">Not supported</canvas>
</div>
<script>
var stage = new createjs.Stage("gameCanvas");
var can = document.getElementById("gameCanvas");
var ctx = can.getContext("2d");
var obj = [];
function drawTriangle() {
ctx.beginPath();
ctx.moveTo(1, 20);
ctx.lineTo(20, 100);
ctx.lineTo(70, 100);
ctx.closePath();
ctx.stroke();
}
function startGame() {
obj[1] = new createjs.DOMElement(document.getElementById("eqn1"));
obj[1].x = 40;
obj[1].y = 50;
stage.addChild(obj[1]);
obj[2] = new createjs.DOMElement(document.getElementById("eqn2"));
obj[2].x = 300;
obj[2].y = 50;
stage.addChild(obj[2]);
stage.update();
drawTriangle();
}
</script>
</body>
</html>
You can see I created a new function drawTriangle it will be called at the end of your startGame that way the triangle is the last item drawn in the canvas.
I'm not sure why you needed the Ticker so I remove it, same with the other functions, they did not make much sense to me, no need for what you are trying to accomplish at the moment.
Now to your problem... in my implementation I have the drawTriangle as the last action in the startGame, but if we change the order, to something like this:
drawTriangle();
stage.update();
The triangle disappears!
My educated guess is that stage.update() clears the entire canvas and draws what it "knows" the triangle drawing is happening outside the stage so we need to always draw it after.
Looking at the code documentation for update:
https://www.createjs.com/docs/easeljs/files/easeljs_display_Stage.js.html#l349
there is an if statement if (this.autoClear) { that does exactly what we are seeing in your sample, and the default value of autoClear is true:
https://www.createjs.com/docs/easeljs/classes/Stage.html#property_autoClear
Also worth pointing out... there is a native createjs way to draw lines:
https://createjs.com/docs/easeljs/classes/Graphics.html#method_moveTo
https://createjs.com/docs/easeljs/classes/Graphics.html#method_lineTo
There is nothing wrong with your approach, you are using both createjs and directly drawing in the canvas via getContext("2d") you just have to plan accordingly, but my recommendation, if there is a native approach I would stick with that, here is a sample code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Math Game</title>
<script src="//code.createjs.com/createjs-2013.09.25.combined.js"></script>
</head>
<body onload="startGame();">
<div class="canvasHolder1">
<div id="eqn1"> 3+3=<input type="text" id="q1" /></div>
<canvas id="gameCanvas" width="600" height="160">Not supported</canvas>
</div>
<script>
function startGame() {
var stage = new createjs.Stage("gameCanvas");
var eqn1 = new createjs.DOMElement(document.getElementById("eqn1"));
eqn1.x = eqn1.y = 50;
stage.addChild(eqn1);
var triangle = new createjs.Shape();
triangle.graphics.beginStroke("black")
triangle.graphics.moveTo(1, 20);
triangle.graphics.lineTo(20, 100);
triangle.graphics.lineTo(70, 100);
triangle.graphics.lineTo(1, 20);
stage.addChild(triangle);
stage.update();
}
</script>
</body>
</html>

Draw a pendulum using DOM

Here is the code, I am drawing 2 circles and 2 lines and an additional line appears parallel to second line.Here is a screenshot
<html>
<head>
<body>
<canvas id="Panel" height=500 width=500 style ="border: 1px dotted green">
</canvas>
</body>
<script>
var canvas = document.getElementById("Panel");
var draw = canvas.getContext("2d");
draw.beginPath();
draw.arc(canvas.width/2,100,10,2*Math.PI,false);
draw.fillSytle="black";
draw.fill();
draw.arc(canvas.width/2,200,10,2*Math.PI,false);
draw.fillSytle="black";
draw.fill();
draw.moveTo(canvas.width/2,0);
draw.lineTo(canvas.width/2,100);
draw.moveTo(canvas.width/2,100);
draw.lineTo(canvas.width/2,200);
draw.stroke();
</script>
</head>
</html>
Check the snippet below. You just need to draw two separate forms
var canvas = document.getElementById("Panel");
var draw = canvas.getContext("2d");
draw.beginPath();
draw.arc(canvas.width/2 -50,200,10,2*Math.PI,false);
draw.fillSytle="black";
draw.fill();
draw.moveTo(canvas.width/2 -50,0);
draw.lineTo(canvas.width/2 -50,200);
draw.stroke();
var draww = canvas.getContext("2d");
draww.beginPath();
draww.arc(canvas.width/2 +50,200,10,2*Math.PI,false);
draww.fillSytle="black";
draww.fill();
draww.moveTo(canvas.width/2 +50,0);
draww.lineTo(canvas.width/2 +50,200);
draww.stroke();
<canvas id="Panel" height=500 width=500 style ="border: 1px dotted green">
</canvas>

Why doesn't context.drawImage() work in html canvas?

I'm trying to put the image file "sticky.png" into a canvas box, but all I'm getting is a blank canvas. Can anyone point out what I'm doing wrong and/or give me code that works?
<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #000000;">
</canvas>
<body>
<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var sticky = new Image();
sticky.onload = function() {
context.drawImage(sticky, 0, 0);
sticky.src = "sticky.png";
};
</script>
</body>
You need to include the sticky.src before sticky.onload.
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;"></canvas>
<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var sticky = new Image();
sticky.src = "sticky.png";
sticky.onload = function() {
context.drawImage(sticky, 0, 0);
};
</script>
</body>
Fiddle
sometimes as a workAround we have to load the image before the canvas. It's very unusual, but it WORKS. And then you just hide the image. Don't forget to use setTimeOut to wait till image is loaded!
setTimeout("paintStar()", 2000);
function paintStar() {
var canva3 = document.getElementById('canvas3');
canva3.width = 640;
canva3.height = 480;
var ct3 = canva3.getContext('2d');
var img = new Image();
img.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3DlDGTyfaFMtUf9GYykLglqfS8GzHbeKRV5vDfHraV1ihNIYo';
ct3.drawImage(img, 0, 0);
ct3.drawImage(img, 0, 0, 20, 20, 10, 200, 20, 20);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CANVAS</title>
<style>
.canvas-1 {
width: 640px;
height: 480px;
border: 1px solid #777;
}
.img-1 {
display: none;
}
</style>
<script src="canva3.js" defer></script>
</head>
<body>
<div class="img-1"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQ3DlDGTyfaFMtUf9GYykLglqfS8GzHbeKRV5vDfHraV1ihNIYo" alt=""></div>
<canvas id="canvas3" style="border: 2px solid #444;">Doesn't work!</canvas>
</body>
</html>

Canvas: Insert fading rectangle between drawn image and clip

I am trying to create a rectangle which will fade on top of an image that is being clipped dynamically.
However any instance of creating a rectangle goes behind the drawn image, and I can't seem to figure out how to place it on top so both the shape and image become clipped.
Here is a Fiddle of where I am currently: JSFiddle
Here is my html:
<div id='demo'>
<canvas id="canvas" width="200px" height="200px"></canvas>
<img id="img" src="http://www.filterforge.com/more/help/images/size200.jpg" />
</div>
Here is my javascript:
function init(){
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
var r = 1;
function draw(){
c.beginPath();
c.arc(100,100,r,0,2*Math.PI,false);
r = r + 1;
// Start Image
c.save();
c.clip();
var img = document.getElementById('img');
c.drawImage(img,0,0);
c.restore();
// The Rectangle I am also trying to mask
c.fillStyle = "rgba(0,0,0,0.025)"
c.fillRect(0, 0, 200, 200);
c.save();
c.clip();
c.restore();
if(r < 100){
requestAnimationFrame(draw);
}
r++;
}
requestAnimationFrame(draw);
}
init();
I would appreciate any help you guys can offer.
Thanks,
Here's the order you want for your clipping:
context.save
define the clipping region (eg your arc)
drawImage
context.restore
Demo: http://jsfiddle.net/m1erickson/YS45U/
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
var r = 0;
var img=new Image();
img.onload=function(){
draw();
};
img.src="http://www.filterforge.com/more/help/images/size200.jpg";
function draw(){
// request another animation if not 100%
if(++r<100){
requestAnimationFrame(draw);
}
// save the unclipped context
c.save();
// set the clipping region
c.beginPath();
c.arc(100,100,r,0,2*Math.PI,false);
c.closePath();
c.clip();
// draw the image into the clipped region
c.drawImage(img,0,0);
// restore the canvas context
c.restore();
}
$("#stop").click(function(){});
}); // end $(function(){});
</script>
</head>
<body>
<button id="stop">Stop</button><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Display whole image in circulr shape using Javascript or HTML5

How can I display whole image in circulr shape using Javascript or HTML5. I tried the code below but with this code only part of the image will be converted into circular shape. How can I make the whole display in circular shape?
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#myCanvas {
border: 1px solid #9C9898;
}
</style>
<script type="text/javascript" >
</script>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<div id="myCanvas"></div>
<script>
var ctx = document.getElementById('myCanvas').getContext("2d");
ctx.arc(100,100, 50, 0, Math.PI*2,true); // you can use any shape
ctx.clip();
var img = new Image();
img.addEventListener('load', function(e) {
ctx.drawImage(this, 0, 0, 200, 300);
}, true);
img.src="images/hospital_review_profile_placeholder.png";
</script>
</body>
</html>
Instead of using ctx.clip(), you would resize and reposition your image to fit in your circle.
Here is code that will resize your image to its largest size that will fit in the circle.
Then the code positions the resized image properly in the circle.
Here is a Fiddle --- http://jsfiddle.net/m1erickson/s6MzZ/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var radius=50; // circle radius
var fullWidth=200; // actual width of image in pixels
var fullHeight=300; // actual height of image in pixels
var centerX=100; // center X coordinate of the circle
var centerY=100; // center Y coordinate of the Circle
// the image must be resized to fit into the circle
// Call CalcResizedImageDimensions() to get the resized width/height
var size=CalcResizedImageDimensions(radius,fullWidth,fullHeight);
var rectX=centerX-size.width/2; // the X coordinate of the resized rectangle
var rectY=centerY-size.height/2 // the Y coordinate of the resized rectangle
ctx.beginPath();
ctx.arc(centerX,centerY,radius,0,Math.PI*2,true);
// I illustrate with just a rectangle
// you would drawImage() instead
ctx.rect(rectX,rectY,size.width,size.height);
ctx.stroke();
function CalcResizedImageDimensions(r,w,h){
var d=2*r;
var newH=(d*h)/Math.sqrt(w*w+h*h);
var newW=w/h*newH;
return({width:newW,height:newH});
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=200 height=200></canvas>
</body>
</html>

Categories

Resources