Draw rectangle over uploaded image - javascript

Once I upload an image I make 2 clicks over it. That's how (x1,y1) and (x2,y2) are obtained. Given these 4 numbers I waanna draw a rectangle over the image by means for example of P5.js. Then I should say rect(x1,y1,x2,y2) but this never happens. How can I deal with this problem (maybe not by P5)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
</head>
<body>
<div id="app">
<button v-on:click="isHidden = false">Load img</button>
<img onclick="showCoords(event)" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>
<script>
var test = new Vue({
el: '#app',
data: {
src: ["cat.jpg", "dog.jpg"],
z: Math.round(Math.random()),
isHidden: true,
}
})
var k=0;
var koors = [];
var flag = false;
function showCoords(event) {
if (k===0){
koors[0] = event.clientX;
koors[1] = event.clientY;
k+=1;
} else if (k===1){
flag = true;
koors[2] = event.clientX;
koors[3] = event.clientY;
}
if ((koors[3] != 0) && (flag)){
console.log(koors)
}
}
//p5
function setup(){
}
function draw(){
console.log(koors[0],koors[1],koors[2],koors[3]);
rect(koors[0],koors[1],koors[2],koors[3])
}
</script>
<script src="p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<script src="js.js"></script>
</body>
</html>

P5 needs a canvas for rendering. If you don't initialize one, it creates it himself (and you are in trouble).
Also, P5 is powerful library, it has tools for events, image processing etc. For current example I wouldn't use any other library (vue).
I created canvas on top of the image (css) and rest is playing with P5.
var test = new Vue({
el: '#app',
data: {
src: [ "https://i.stack.imgur.com/XZ4V5.jpg", "https://i.stack.imgur.com/7bI1Y.jpg"],
z: Math.round(Math.random()),
isHidden: false,
}
})
var recStart;
var coords = {};
/*******************************************************************
* P5 setup
* run once, use for initialisation.
*
* Create a canvas, change dimensions to
* something meaningful(like image dim)
********************************************************************/
function setup(){
var canvas = createCanvas(480, 320);
canvas.parent('app');
}
/*******************************************************************
* P5 draw
* endless loop.
*
* Lets redraw rectangle until second click.
********************************************************************/
function draw(){
if(recStart)
drawRect();
}
/*******************************************************************
* drawRect
*
* Draw a rectangle. mouseX and mouseY are P5 variables
* holding mouse current position.
********************************************************************/
function drawRect(){
clear();
noFill();
stroke('red');
rect(coords.x, coords.y, mouseX-coords.x, mouseY-coords.y);
}
/*******************************************************************
* P5 mouseClicked
*
* P5 event. Again, mouseX and mouseY are used.
********************************************************************/
mouseClicked = function() {
if (mouseButton === LEFT) {
if(!recStart){ // start rectangle, give initial coords
coords.x = mouseX;
coords.y = mouseY;
recStart = true; // draw() starts to draw
} else {
recStart = false; // stop draw()
drawRect(); // draw final rectangle
coords = {}; // clear coords
}
}
};
canvas {
width: 500px;
height:500px;
z-index: 2;
border:1px solid;
position:absolute;
left: 0;
top: 0;
}
img {
z-index: 1;
position: absolute;
border: 2px solid black;
left: 0;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
<div id="app">
<img id="pilt" v-if="!isHidden" v-bind:src="src[z]"></img>
</div>

It seems that you don't call draw anywhere. You may also consider draw the image into a canvas and than draw rect in this canvas. Checking if koors[3] != 0 is really risky as user may click at 0th pixel.

Related

Using variable font inside WEBGL canvas, p5 js

I have a WEBGL canvas in which I am loading a 3d model. I also have a text in variable font which I create with createP. The problem is that I need the text to be between the background and the 3d model. But I can only have the text in front of the canvas (on top of 3d model). Is there any way I can achieve this?
Ps. Creating the text with text() does not allow me to have variable weight value.
let kalameh;
var cnv;
let img;
function preload(){
img = loadImage('assets/lines.png');
kalameh = loadModel('kalameh.obj');
}
function setup() {
cnv = createCanvas(700, 700, WEBGL);
var x = (windowWidth - width) / 2;
var y = (windowHeight - height) / 2;
cnv.position(x, y);
wordA = createP('my text');
}
function draw() {
background(220, 220, 220);
wordA.style('font-size', '110px');
wordA.style('font-weight', '200');
wordA.style('font-stretch', '200%');
wordA.style('align', 'center');
wordA.position(40,25);
image(img, -1*windowWidth/2, -1*windowHeight/2, windowWidth, windowHeight);
translate (0,0,100);
pointLight(255,255,255, -350,0,400);
pointLight(255,255,255, 350,0,400);
ambientMaterial(255);
noStroke();
scale (0.25);
model(kalameh);
}
You could create two sketches (and thus two canvases) and assign z-index properties of -1 and 1 to make them foreground and background sketches, respectively. You can then sandwich the paragraph element that you created between the two canvases by giving it a z-index of 0. You can then make the foreground sketch transparent by calling clear() at the beginning of the draw loop.
In the code snippet below, the 3D object is in front of the text paragraph, whereas the white square of the "background" is behind the text.
let testP;
new p5(function(p){
p.setup = function() {
const foregroundCanvas = p.createCanvas(400, 400, p.WEBGL);
foregroundCanvas.id("foregroundSketch");
foregroundCanvas.position(0, 0);
p.normalMaterial();
testP = p.createP("In front of background / behind object ")
testP.position(95, 115);
testP.id("sandwichedParagraph")
p.angleMode(p.RADIANS)
}
p.draw = function() {
p.clear();
//drag to move the world.
// p.orbitControl();
p.push();
let rotateAngle = p.sin(p.frameCount/50);
p.rotateX(rotateAngle/2);
p.rotateY(-rotateAngle);
p.rotateZ(rotateAngle);
p.box(200, 100, 40);
p.pop();
}
}, "foregroundSketch");
new p5(function(p){
p.setup = function() {
const backgroundCanvas = p.createCanvas(400, 400);
// backgroundCanvas.parent("wrapper")
backgroundCanvas.position(0, 0);
backgroundCanvas.id("backgroundSketch")
p.noStroke();
}
p.draw = function() {
p.background(200);
let shiftAmount = p.map(p.sin(p.frameCount/60), -1, 1, 80, 310);
p.rect(shiftAmount, 120, 40, 40);
}
}, "backgroundSketch");
html, body {
margin: 0;
padding: 0;
}
/* The sketch with the white square has z-index of -1 (background!) */
#backgroundSketch {
z-index: -1;
position: absolute;
}
/* The <p> has z-index of 0 (sandwiched between both sketches)*/
#sandwichedParagraph {
z-index: 0;
position: absolute;
}
/* The sketch with the object has z-index of 1 (foreground!)*/
#foregroundSketch {
z-index: 1;
position: absolute;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>

How do I make multiple moving squares on a canvas?

So far I have made a moving square that when the button is clicked in the HTML file, calls the draw() function and draws a red square in the canvas area that moves accross the canvas. How do I make it so that the same function draw() can create multiple moving sqaures?
Here's the code so far:
var x = 10;
var y = 10;
function draw(){
var can = document.getElementById("myCanvas");
var ctx = can.getContext("2d");
var x = 1;
setInterval(function(){
ctx.clearRect(0,0, can.width, can.height);
ctx.fillRect(x, 20, 75, 75);
ctx.fillStyle ="red";
x=x+5;
}, 500
);
}
Not sure that my solution is good, I'm just starting to learn js, but hope it will helpful.
// variables declaration. I suggest to use Arrays
// for store individual rectangle parameters.
// rectangle start coords x and y
var rcx = [];
var rcy = [];
// delta to move x, y
var dx = [];
var dy = [];
// rectangle size (if you want it variable)
var size =[];
// init canvas
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// create and collect rectangles parameters
// on window load (here 100 rectangles created)
// with unique coords, deltas to move,
// and sizes for each rectangle.
window.onload = function() {
for (var i=0; i<100; i++) {
// in this solution all parameters randomized,
// but you can set whatever you want.
rcx[i]=(Math.floor(Math.random() * Math.floor(canvas.width)));
rcy[i]=(Math.floor(Math.random() * Math.floor(canvas.height)));
dx[i]= (Math.floor(Math.random() * Math.floor(3))-1);
dy[i]=(Math.floor(Math.random() * Math.floor(3))-1);
size[i] = (Math.floor(Math.random() * Math.floor(8)));
}};
// it is optional, but i decide
// made function for rectangle declaration.
// It will looks more compact when rendering.
function rect(x, y, size){
ctx.fillRect(x, y, size, size/2 );
ctx.fillStyle = "rgba(255,255,255,1)";
}
// finally all together into function draw()
function draw(){
setInterval(function(){
ctx.clearRect(0,0, canvas.width, canvas.height);
for (var j=0; j<100; j++) {
// read arrays
// render rectangle with params from arrays
rect(rcx[j],rcy[j],size[j]);
// add delta to move (x,y)
// and rewrite new coords to arrays
rcx[j]=rcx[j]+dx[j];
rcy[j]=rcy[j]+dy[j]};
}, 100
);
};
//rendering animation
draw();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#canvas {
width: 500px;
height: 500px;
background-color: #ccc;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="js1.js"></script>
</body>
</html>
Sorry, didn't mention about button. So for the btn changes are simple.
Create btn div in html,
Add listener on this div. Рut params in arrays if button is pushed. Instead of generation by random as it was in my solution before.
Read arrays and render all rectangles from it.
// variables declaration. I suggest to use Arrays for store individual rectangle parameters.
// rectangle start coords x and y
var rcx = [];
var rcy = [];
// delta to move x, y
var dx = [];
var dy = [];
// rectangle size (if you want it variable)
var size =[];
//counter for created rectangles
var i=0;
// init canvas
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
// create and collect rectangles parameters on btn push
// with unique coords, deltas to move, and sizes for each rectangle.
var btn =document.getElementById('btn');
btn.addEventListener( 'click', function() {
//count every time you push the btn and create rect
i=i+1;
//generate rect params x,y, delta x, delta y, size
rcx[i]=20;
rcy[i]=20;
dx[i]=1
dy[i]=0
size[i] = 8;
});
// it is optional, but i decide made function for rectangle declaration. It will looks more compact when rendering.
function rect(x, y, size){
ctx.fillRect(x, y, size, size/1.5);
ctx.fillStyle = "red";
}
// finally all together into function draw()
function draw(){
setInterval(function(){
ctx.clearRect(0,0, canvas.width, canvas.height);
for (var j=1; j<rcx.length; j++) {
// read arrays
// render rectangle with params from arrays
rect(rcx[j],rcy[j],size[j]);
// add delta to move (x,y) and rewrite new coords to arrays
rcx[j]=rcx[j]+dx[j];
rcy[j]=rcy[j]+dy[j]};
}, 100
);
};
//rendering animation
draw();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
margin: 0 auto;
padding: 0;
background-color: rgb(17, 0, 28);
}
#container{
position: relative;
margin-top: 10px;
margin-left: 50px;
}
#canvas {
z-index: 0;
position:fixed;
align-self: center;
justify-self: center;
width: 80vw;
height: 50vw;
background-color: #ccc;
}
#btn {
margin: 20px 20px 20px 0px;
padding: 10px;
position:static;
top: 30px;
font-family: 'Roboto', sans-serif;
width: 65px;
background-color: brown;
cursor: pointer;
}
#btn:hover {
background-color: red;
}
#btn:active {
background-color: coral;
}
</style>
</head>
<body>
<div id="container">
<div id="btn"> Push me </div>
<canvas id="canvas"></canvas>
</div>
<script src="js1.js"></script>
</body>
</html>

Referencing canvas with button in Javascript

Ok so I'm attempting to have a webpage with two buttons. Each of these buttons, when clicked, creates a new canvas and calls a different draw function. The first draw function would draw large circles where the users mouse is and small ones when the mouse is pressed. The other draw function does the same thing except small circles when the mouse is unpressed and large ones when it is. I'm not having a problem referencing one of these with the button but the other button doesn't seem to call its draw function. sketch2.js seems to be working fine but it seems that the draw function in sketch.js is not being called. Any advice on how I should go about fixing this is greatly appreciated!
Below is my HTML code:
<html>
<head>
<meta charset="UTF-8">
<button id="myBtn">little then big</button>
<div id="holder"></div>
<button id="myBtn2">big then little</button>
<div id="holder2"></div>
<style> body {padding: 0; margin:0;} </style>
</head>
<body>
<script type="text/javascript" src = "/Users/bburke95/Desktop/JS/p5.dom.js"> </script>
<script language="javascript" type="text/javascript" src="../p5.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="sketch2.js"></script>
</body>
</html>
This is my sketch.js class
btn = document.getElementById("myBtn");
var q;
btn.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder").innerHTML = '<canvas id="myCanvas" width="490" height="220"></canvas>';
q = 1;
set = 0;
}
function draw() {
if (q == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(255);
x = 160;
y = 160;
} else {
fill(0);
x = 80;
y = 80;
}
ellipse(mouseX, mouseY, x, y);
}
}
and this is my sketch2.js class
btn2 = document.getElementById("myBtn2");
var set;
btn2.onclick = function setup() {
createCanvas(640, 480);
document.getElementById("holder2").innerHTML = '<canvas id="myCanvas2" width="490" height="220"></canvas>';
set = 1;
q = 0;
}
function draw() {
if (set == 1) {
var x;
var y;
if (mouseIsPressed) {
fill(0);
x = 80;
y = 80;
} else {
fill(255);
x = 160;
y = 160;
}
ellipse(mouseX, mouseY, x, y);
}
}
If you want to run more than one P5.js processing sketches on the same page, you have to use "instance mode" to ensure that all the functions aren't cluttering the global namespace (which is a good idea anyway) so they don't overwrite one another.
From their Github project, you can instantiate new sketches like this:
var s = function( p ) {
var x = 100;
var y = 100;
p.setup = function() {
p.createCanvas(700, 410);
};
p.draw = function() {
p.background(0);
p.fill(255);
p.rect(x,y,50,50);
};
};
var myp5 = new p5(s);

How to write a loop so that I will draw to user canvas?

I have a canvas element. I have a few troubles, how to draw to user canvas in "realtime",.. So, that my drawing is not already there when they open the site, but rather to draw to the canvas like somebody is actually drawing... So looping through the coordinates.
That's what I tried so far but it's BAAD! It's drawing slowly and it takes a lot of CPU.
// Pencil Points
var ppts = [];
/* Drawing on Paint App */
tmp_ctx.lineWidth = 4;
tmp_ctx.lineJoin = 'round';
tmp_ctx.lineCap = 'round';
tmp_ctx.strokeStyle = '#4684F6';
tmp_ctx.fillStyle = '#4684F6';
// Tmp canvas is always cleared up before drawing.
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.beginPath();
var timer = 0;
$.timer(500, function() {
ppts.push({x: 10*timer, y: 5*timer});
timer++;
})
$.timer(10, function() {
if (timer > 250) {
timer = 0;
clearTempCanvas();
} else {
for (var i = 1; i < ppts.length - 2; i++) {
var c = (ppts[i].x + ppts[i + 1].x) / 2;
var d = (ppts[i].y + ppts[i + 1].y) / 2;
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
}
console.log(i);
tmp_ctx.stroke();
}
})
function clearTempCanvas() {
// Writing down to real canvas now
ctx.drawImage(tmp_canvas, 0, 0);
// Clearing tmp canvas
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
// Emptying up Pencil Points
ppts = [];
}
Here's an example for you to learn from: http://jsfiddle.net/m1erickson/j4HWS/
It works like this:
define some points to animate along and put those points in an array points.push({x:25,y:50})
use requestAnimationFrame to create an animation loop
break each line segment into 100 sub-segments and animate along those sub-segments
Example code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script 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");
ctx.lineWidth=2;
ctx.strokeStyle="blue";
var points=[];
points.push({x:125,y:125});
points.push({x:250,y:200});
points.push({x:125,y:200});
points.push({x:125,y:125});
var pointIndex=1;
var linePct=0;
var continueAnimating=true;
var img=new Image();img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/pen.png";
function start(){
animate();
}
function draw(pointIndex,linePct){
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw fully completed lines
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=1;i<pointIndex;i++){
ctx.lineTo(points[i].x,points[i].y);
}
// draw current line-in-process
var pos=getLineXYatPercent(points[pointIndex-1],points[pointIndex],linePct/100);
ctx.lineTo(pos.x,pos.y);
ctx.stroke();
// draw the pen
ctx.drawImage(img,pos.x-93,pos.y-92);
}
function animate() {
if(!continueAnimating){return;}
requestAnimationFrame(animate);
// Drawing code goes here
draw(pointIndex,linePct);
if(++linePct>100){
linePct=1;
if(++pointIndex>points.length-1){
continueAnimating=false;
}
}
}
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>

Adding more images to the canvas to drag and drop

I want to be able to spawn a new image to the canvas at the click of a button, rather than having to manually edit the code.
I have the following HTML5/JavaScript code that allows images to be dragged and dropped between multiple canvases and it works perfectly for what I require.
What I am doing:
<canvas style="float: left" height="125" width="400" id="cvs1">[No canvas support]</canvas>
<canvas style="float: left; margin-left: 100px" height="125" width="400" id="cvs2">[No canvas support]</canvas>
<script src="http://www.rgraph.net/libraries/RGraph.common.core.js" ></script>
<script>
window.onload = function ()
{
var canvas1 = document.getElementById("cvs1");
var canvas2 = document.getElementById("cvs2");
var context1 = canvas1.getContext('2d');
var context2 = canvas2.getContext('2d');
var imageXY = {x: 5, y: 5};
/**
* This draws the image to the canvas
*/
function Draw ()
{
//Clear both canvas first
canvas1.width = canvas1.width
canvas2.width = canvas2.width
//Draw a red rectangle around the image
if (state && state.dragging) {
state.canvas.getContext('2d').strokeStyle = 'red';
state.canvas.getContext('2d').strokeRect(imageXY.x - 2.5,
imageXY.y - 2.5,
state.image.width + 5,
state.image.height + 5);
}
// Now draw the image
state.canvas.getContext('2d').drawImage(state.image, imageXY.x, imageXY.y);
}
canvas2.onclick =
canvas1.onclick = function (e)
{
if (state && state.dragging) {
state.dragging = false;
Draw();
return;
}
var mouseXY = RGraph.getMouseXY(e);
state.canvas = e.target;
if ( mouseXY[0] > imageXY.x
&& mouseXY[0] < (imageXY.x + state.image.width)
&& mouseXY[1] > imageXY.y
&& mouseXY[1] < (imageXY.y + state.image.height)) {
state.dragging = true;
state.originalMouseX = mouseXY[0];
state.originalMouseY = mouseXY[1];
state.offsetX = mouseXY[0] - imageXY.x;
state.offsetY = mouseXY[1] - imageXY.y;
}
}
canvas1.onmousemove =
canvas2.onmousemove = function (e)
{
if (state.dragging) {
state.canvas = e.target;
var mouseXY = RGraph.getMouseXY(e);
// Work how far the mouse has moved since the mousedon event was triggered
var diffX = mouseXY[0] - state.originalMouseX;
var diffY = mouseXY[1] - state.originalMouseY;
imageXY.x = state.originalMouseX + diffX - state.offsetX;
imageXY.y = state.originalMouseY + diffY - state.offsetY;
Draw();
e.stopPropagation();
}
}
/**
* Load the image on canvas1 initially and set the state up with some defaults
*/
state = {}
state.dragging = false;
state.canvas = document.getElementById("cvs1");
state.image = new Image();
state.image.src = 'http://www.rgraph.net/images/logo.png';
state.offsetX = 0;
state.offsetY = 0;
state.image.onload = function ()
{
Draw();
}
}
</script>
This can also be seen on this JS Fiddle (Note: you have to click the image before you can drag it)
The problem I am having:
I would like to add more images to the canvases so that any of the images can then be dragged and dropped between however many canvases I choose to create.
I can quite easily add more canvases to the page to drag and drop between, however when it comes to adding/spawning more images to the canvases I cannot get it to work.
The only way I can think of being able to do this is by repeating the Draw() function for every single image that gets added. That would mean if I wanted 30 images to be able to drag and drop between 10 different canvases for example, I would need to repeat the Draw() function 30 times. Surely that cannot be the best way to do this?
Unless I am missing something very obvious I cannot see another way of doing this?
Here’s how to configure your code to create multiple objects and click-drag between canvases.
Demo: http://jsfiddle.net/m1erickson/Bnb6A/
Code an object factory function that creates new draggable objects and put all new objects in an array.
Keep this information about each draggable object:
dragging (true/false) indicating if this object is currently being dragged
image: the image for this object
x,y: the current top,left position of this object
width,height: the size of this object
offsetX,offsetY: indicates where the mouse clicked relative to top,left of this object
draw: (a function) that allows this object to draw itself (surrounded by a red rect if it’s being dragged)
On click:
Get the mouse position
Clear both canvases
Iterate through the object array
If an object is being dragged, unset the dragging flag
If an object is now selected, set the dragging flag and set the offsetX,offsetY for the starting mouse position relative to this object.
Redraw all objects
On mousemove:
Get the mouse position
Clear both canvases
Iterate through the object array
If an object is being dragged, move it to the mouse position (setting x,y adjusted for the offset)
Redraw all objects
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{ border: 1px solid #808080; }
</style>
<script>
$(function(){
var canvas1 = document.getElementById("cvs1");
var canvas2 = document.getElementById("cvs2");
var contexts=[];
contexts.push(canvas1.getContext('2d'));
contexts.push(canvas2.getContext('2d'));
function clearAll(){
//Clear both canvas first
canvas1.width = canvas1.width
canvas2.width = canvas2.width
}
canvas1.onclick=function(e){ handleClick(e,1); };
canvas2.onclick=function(e){ handleClick(e,2); };
//
function handleClick(e,contextIndex){
e.stopPropagation();
var mouseX=parseInt(e.clientX-e.target.offsetLeft);
var mouseY=parseInt(e.clientY-e.target.offsetTop);
clearAll();
for(var i=0;i<states.length;i++){
var state=states[i];
if(state.dragging){
state.dragging=false;
state.draw();
continue;
}
if ( state.contextIndex==contextIndex
&& mouseX>state.x && mouseX<state.x+state.width
&& mouseY>state.y && mouseY<state.y+state.height)
{
state.dragging=true;
state.offsetX=mouseX-state.x;
state.offsetY=mouseY-state.y;
state.contextIndex=contextIndex;
}
state.draw();
}
}
canvas1.onmousemove = function(e){ handleMousemove(e,1); }
canvas2.onmousemove = function(e){ handleMousemove(e,2); }
//
function handleMousemove(e,contextIndex){
e.stopPropagation();
var mouseX=parseInt(e.clientX-e.target.offsetLeft);
var mouseY=parseInt(e.clientY-e.target.offsetTop);
clearAll();
for(var i=0;i<states.length;i++){
var state=states[i];
if (state.dragging) {
state.x = mouseX-state.offsetX;
state.y = mouseY-state.offsetY;
state.contextIndex=contextIndex;
}
state.draw();
}
}
var states=[];
var img=new Image();
img.onload=function(){
states.push(addState(0,0,img));
}
img.src="http://www.rgraph.net/images/logo.png";
function addState(x,y,image){
state = {}
state.dragging=false;
state.contextIndex=1;
state.image=image;
state.x=x;
state.y=y;
state.width=image.width;
state.height=image.height;
state.offsetX=0;
state.offsetY=0;
state.draw=function(){
var context=contexts[this.contextIndex-1];
if (this.dragging) {
context.strokeStyle = 'red';
context.strokeRect(this.x,this.y,this.width+5,this.height+5)
}
context.drawImage(this.image,this.x,this.y);
}
state.draw();
return(state);
}
$("#more").click(function(){
states.push(addState(states.length*100,0,img));
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="more">Add Image</button><br>
<canvas height="125" width="300" id="cvs1">[No canvas support]</canvas><br>
<canvas height="125" width="300" id="cvs2">[No canvas support]</canvas>
</body>
</html>

Categories