I have an image of 4000px by 3000px. I want to display this image on an html page and allow users to select coordinates over this image.
Actually I have to replicate from this:
https://www.botb.com/CompetitionPlay.aspx?SiteID=1®ion=GB&cid=2ca08b9b-4717-474c-b5ec-1e6a40df6d54&play=1
(Please register and see this element. Its free to sign up)
Actually I want to display this 4000x3000px picture in 700x500px div size but the user should be able to select coordinates in the picture relative to its actual size i.e 4000x3000px.
The problem with simple approach of scaling the pixels is that the user is only able to select coordinates from downscaled pixels. I want the user to able to select a coordinate from 4000*3000 possibilities
How can I fix a large dimensions image into that size and make magnify tool just like the one in the above? Is it possible in using html5 canvas?
If you can share any jquery plugin for this then I will be very grateful.
Image at 25% size:
Image with magnified section (magnified section is 100% size)
Here's code to magnify the image when the user holds the mouse down over their desired magnification point.
The code uses a second overlaying canvas to present a portion of the magnified (full-sized) image.
Example code and a Demo:
This starting example uses a fixed size magnification viewport, but you can adjust to let the user use mousedown+mouseup to define a variable sized viewport.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var magifier=document.getElementById("magnifier");
var mctx=magnifier.getContext("2d");
var $magnifier=$('#magnifier');
var mw=100;
var mh=100;
var downscale=0.25;
var upscale=1/downscale;
var iw,ih;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/soccer.jpg";
function start(){
magnify();
iw=img.width;
ih=img.height;
cw=canvas.width=iw*downscale;
ch=canvas.height=ih*downscale;
ctx.drawImage(img,0,0,cw,ch);
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas,#magnifier").mouseup(function(e){handleMouseUp(e);});
}
function magnify(x,y){
if(!x){$magnifier.css({left:-999}); return;};
$magnifier.css({left:x-mw/2,top:y-mh/2});
mctx.clearRect(0,0,mw,mh);
mctx.drawImage(img,-(x)*upscale+mw/2,-(y)*upscale+mh/2);
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
magnify(x,y);
}
function handleMouseUp(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
magnify();
}
body{ background-color: ivory; }
#container{position:relative;}
#canvas{position:absolute;border:1px solid red;}
#magnifier{position:absolute;border:3px solid blue;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Hold mouse down for magnified view.</h4>
<div id=container>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="magnifier" width=100 height=100></canvas>
</div>
maybe something like this, you can use this to calculate the ratio to the original size too, just do the multiplication.
var element = document.getElementById("box");
element.onmousemove = function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
show(x, y);
}
function show(x, y) {
coords.innerHTML = "(" + x + "," + y + ")";
}
#box {
border: 2px solid black;
background: lightblue;
width: 200px;
height: 150px;
cursor: crosshair;
background-image: url('http://lorempixel.com/200/150/');
}
body {
margin: 10px;
}
Coords <span id="coords">(X,Y)</span>
<div id="box"></div>
Related
I have canvas area, where i can add some images.
And i want to cut whole canvas to parts and download just one part of image.
If i put divs with color overlay canvas, i can't move my elements inside.
But i want to show users which area has been selected and will be downloaded.
Is it possible to show some divs overlay canvas and also manage with canvas?
If don't how can i listening mouseover event for my div which is invisible, because have lower z-index, than my canvas image ?
Instead of trying to color your divs, you use a second (overlay) canvas on top of your image canvas to tint the desired parts of your image canvas underneath.
Define a javascript object representing each part (rectangle) of your canvas.
Place a second overlay canvas over your image canvas and tell it not emit events using CSS: pointer-events:none.
On mousemove, fill the part of the overlay canvas under the mouse with semi-transparent color.
Here is example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var overlay=document.getElementById("overlay");
var octx=overlay.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var selectedPart=1;
var parts=[];
var img=new Image();
img.onload=start;
img.src='https://dl.dropboxusercontent.com/u/139992952/multple/sailboatSmall.png';
function start(){
cw=canvas.width=overlay.width=img.width;
ch=canvas.height=overlay.height=img.height;
octx.font='18px verdana';
octx.textAlign='center';
octx.textBaseline='middle';
octx.lineWidth=0.50;
octx.fillStyle='red';
octx.globalAlpha=0.10;
parts.push({x:0,y:0,w:cw/3,h:ch/2});
parts.push({x:cw/3,y:0,w:cw/3,h:ch/2});
parts.push({x:cw*2/3,y:0,w:cw/3,h:ch/2});
parts.push({x:0,y:ch/2,w:cw/2,h:ch/2});
parts.push({x:cw/2,y:ch/2,w:cw/2,h:ch/2});
ctx.drawImage(img,0,0);
$("#canvas").mousemove(function(e){handleMouseMove(e);});
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
for(var i=0;i<parts.length;i++){
var p=parts[i];
if(x>p.x && x<p.x+p.w && y>p.y && y<p.y+p.h){
if(i==selectedPart){return;}
selectedPart=i;
octx.clearRect(0,0,cw,ch);
octx.fillRect(p.x,p.y,p.w,p.h);
}
}
}
body{ background-color:white; }
#container{position:relative;}
#canvas,#overlay{position:absolute;}
#overlay{pointer-events:none;border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move mouse over image parts</h4>
<div id=container>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="overlay" width=300 height=300></canvas>
</div>
I have an HTML canvas with all different shapes of all different sizes and it is built by parsing information from an external file. I am wondering how I can make it so that hovering the mouse over each shape will display its unique name. I have found resources on how to display text on a mouse hover for the whole canvas, but I need each individual shape to display a unique text. Thanks!
You can use context.isPointInPath to test if your mouse is hovering over one of your shapes.
Create a javascript object representing each shape from the external file.
var triangle={
name:'triangle',
color:'skyblue',
points:[{x:100,y:100},{x:150,y:150},{x:50,y:150}]
};
Create a function that takes a shape-object and makes a Path from that shape-object:
function defineShape(s){
ctx.beginPath();
ctx.moveTo(s[0].x,s[0].y);
for(var i=1;i<s.length;i++){
ctx.lineTo(s[i].x,s[i].y);
}
ctx.closePath();
}
Use context.isPointInPath to test if the mouse is inside the most recently defined path (from step#2).
// define the path to be tested
defineShape(triangle);
// test if the mouse is inside that shape
if(context.isPointInPath(mouseX,mouseY){
// the mouse is inside the shape
}
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
ctx.font='14px verdana';
var shapes=[];
var triangle1={
name:'triangle1',
color:'skyblue',
drawcolor:'skyblue',
points:[{x:100,y:100},{x:150,y:150},{x:50,y:150}]
};
var triangle2={
name:'triangle2',
color:'palegreen',
drawcolor:'palegreen',
points:[{x:220,y:100},{x:270,y:150},{x:170,y:150}]
};
shapes.push(triangle1,triangle2);
$("#canvas").mousemove(function(e){handleMouseMove(e);});
drawAll();
function drawAll(){
for(var i=0;i<shapes.length;i++){
var s=shapes[i];
defineShape(s.points);
ctx.fillStyle=s.drawcolor;
ctx.fill();
ctx.stroke();
if(s.color!==s.drawcolor){
ctx.fillStyle='black';
ctx.fillText(s.name,s.points[0].x,s.points[0].y);
}
}
}
function defineShape(s){
ctx.beginPath();
ctx.moveTo(s[0].x,s[0].y);
for(var i=1;i<s.length;i++){
ctx.lineTo(s[i].x,s[i].y);
}
ctx.closePath();
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// clear the canvas
ctx.clearRect(0,0,cw,ch);
for(var i=0;i<shapes.length;i++){
var s=shapes[i];
// define the shape path we want to test against the mouse position
defineShape(s.points);
// is the mouse insied the defined shape?
if(ctx.isPointInPath(mouseX,mouseY)){
// if yes, fill the shape in red
s.drawcolor='red';
}else{
// if no, fill the shape with blue
s.drawcolor=s.color;
}
}
drawAll();
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Hover the mouse over the shape.</h4>
<canvas id="canvas" width=300 height=300></canvas>
Are you willing to use a library, or are you attached to a purely native canvas implementation? With purely native canvas, this could get quite annoying, because you would have to not only get the mouse coordinates of the pointer, but also keep track of the position of every object and check whether or not the mouse is at that position every time the mouse moves. I coded that functionality once, and it was annoying enough with just a few rectangles to keep track of.
On the other hand, if you use KineticJS to do your canvas drawing (or presumably others; KineticJS is just the one I've used), all that annoyance is handled for you. The objects you create and add to the canvas can have event handlers attached to them using the KineticJS library, and it will be only minimally harder than reacting to mouseover events on any other HTML element. This link shows how to do it.
http://www.html5canvastutorials.com/kineticjs/html5-canvas-listen-or-dont-listen-to-events-with-kineticjs/
Hello I have this script that checks for transparent pixels and non transparent pixels. Now i made it so the result is coming from 100px by 100px rectangle on mouse over:
var data = ctx.getImageData(100,100, canvas.width, canvas.height).data;
And right now it shows on mouse of over the result of Opague area and Transparent area.
I would like somehow to visualise this rectangle on load with a grid overlaying the image and the oppaque boxes and transparent one to have different colours like oppaque is green transparent is red. I need probably on load function? But how should it look?
I am stuck here and need someone to direct me in the right position
and here is my current progress:
https://jsfiddle.net/kdichev/Lnp3k5re/
Since you probably want the game console to still show, you can draw your 100x100 boxes with a reduced alpha (globalAlpha).
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var boxWidth=100;
var boxHeight=100;
var boxRows=Math.ceil(865/boxHeight);
var boxCols=Math.ceil(1152/boxWidth);
var boxes=new Array(boxRows*boxCols);
for(var i=0;i<boxes.length;i++){boxes[i]=false;}
var img=new Image();
img.onload=start;
img.crossOrigin='anonymous';
img.src="http://i.imgur.com/RrHayx8.png?1";
function start(){
ctx.drawImage(img,0,0);
var d=ctx.getImageData(0,0,cw,ch).data;
for(var i=0;i<d.length;i+=4){
if(d[i+3]>200){
var px=parseInt(i/4);
var pixelY=parseInt(px/cw);
var pixelX=px-pixelY*cw;
var boxX=parseInt(pixelX/boxWidth);
var boxY=parseInt(pixelY/boxHeight);
boxes[boxY*boxCols+boxX]=true;
}
}
ctx.globalAlpha=0.25;
ctx.fillStyle='red';
for(var i=0;i<boxes.length;i++){
var y=parseInt(i/boxCols);
var x=i-y*boxCols;
if(boxes[i]==true){
ctx.fillRect(x*boxWidth,y*boxHeight,boxWidth,boxHeight);
}
}
ctx.globalAlpha=1.00;
ctx.fillStyle='black';
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=1152 height=865></canvas>
I want to do something like this in the canvas with Javascript.
I want to blur a square. I looked for it on the internet but I didn't find anything. If I don't have to use an external JS library, it'll be better.
[EDIT]I'm not refering to the Finder Icon but the square that is behind it.[/EDIT]
Stackoverflow's Ken Fyrstenberg has authored a very nice blur script here:
https://github.com/epistemex/realtime-blur-js
Here's an example using Ken's blur plus a tinted 25% opaque rectangle:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/wingedLion.jpg";
function start(){
var tempcanvas=document.createElement("canvas");
var tctx=tempcanvas.getContext("2d");
cw=canvas.width=tempcanvas.width=img.width;
ch=canvas.height=tempcanvas.height=img.height;
var x=50;
var y=250;
var w=325;
var h=75;
tctx.drawImage(img,0,0);
var rtblur;
rtblur=new RTBlur({source:tempcanvas});
rtblur.blur(0.50,tctx);
ctx.drawImage(img,0,0);
ctx.drawImage(tempcanvas, x,y,w,h, x,y,w,h);
ctx.fillStyle='tan';
ctx.globalAlpha=0.250;
ctx.fillRect(x,y,w,h);
ctx.globalAlpha=1.00;
ctx.strokeStyle='darkgray';
ctx.lineWidth=2;
ctx.strokeRect(x,y,w,h);
ctx.font='18px verdana';
ctx.fillStyle='white';
ctx.fillText('A rect with blurred background',x+20,y+30);
ctx.fillText('and a tan 25% opacity tint',x+20,y+55);
}
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red;}
<script src="https://cdn.rawgit.com/epistemex/realtime-blur-js/master/rtblur.js"></script>
<canvas id="canvas" width=300 height=300></canvas>
I have a contract text which is stored into MS SQL VARMAX field. When loaded into a canvas I need to have the user signed in different places. Then need to save the signatures as svg format. But how do I grab the relative positions of each signature? So when I load back the text I can show the signatures in the right positions.
Thanks,
Doron
When the person initially signs the contract, presumably you will have a separate canvas positioned directly over your contract text. The signatory will move the mouse/pen over the canvas to create their signature. The signature will be the only opaque pixels on the canvas.
You can use getImageData to fetch the pixel data for the canvas. Then you can loop through each pixel and save the leftmost, topmost, rightmost and bottommost opaque pixel position. That gives your desired bounding box for the signature.
Here's how to get the bounding box of a signature on the canvas.
function findBoundary(){
var data=ctx.getImageData(0,0,cw,ch).data;
var top=1000000;
var left=1000000;
var right=-10;
var bottom=-10;
for(var y=0;y<ch;y++){
for(var x=0;x<cw;x++){
var n=(y*cw+x)*4+3;
if(data[n]>200){
if(x<left){left=x;}
if(x>right){right=x;}
if(y<top){top=y;}
if(y>bottom){bottom=y;}
}
}}
return({x:left,y:top,width:right-left+1,height:bottom-top+1});
}
Example code and a Demo:
Note: This simple demo isn't meant to be a signature capture app--I assume you already have a full signature app. It just draws a stoke as you drag the mouse and shows you the bounding box of the stroke when you release the mouse.
var $results=$('#results');
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
ctx.lineCap = "round";
ctx.lineWidth=2;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
var isDown=false;
var startX;
var startY;
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUpOut(e);});
$("#canvas").mouseout(function(e){handleMouseUpOut(e);});
function findBoundary(){
var data=ctx.getImageData(0,0,cw,ch).data;
var top=1000000;
var left=1000000;
var right=-10;
var bottom=-10;
for(var y=0;y<ch;y++){
for(var x=0;x<cw;x++){
var n=(y*cw+x)*4+3;
if(data[n]>200){
if(x<left){left=x;}
if(x>right){right=x;}
if(y<top){top=y;}
if(y>bottom){bottom=y;}
}
}}
return({x:left,y:top,width:right-left+1,height:bottom-top+1});
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
startX=parseInt(e.clientX-offsetX);
startY=parseInt(e.clientY-offsetY);
// Put your mousedown stuff here
ctx.clearRect(0,0,cw,ch);
ctx.lineWidth=3;
ctx.strokeStyle='black';
isDown=true;
}
function handleMouseUpOut(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
isDown=false;
var pos=findBoundary();
ctx.strokeStyle='red';
ctx.lineWidth=1;
ctx.globalAlpha=0.50;
ctx.strokeRect(pos.x,pos.y,pos.width,pos.height);
ctx.globalAlpha=1.00;
$results.text(
'Signature boundary x/y: '
+parseInt(pos.x)+'/'
+parseInt(pos.y)+', width/height: '
+parseInt(pos.width)+'/'
+parseInt(pos.height)
);
}
function handleMouseOut(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mouseOut stuff here
isDown=false;
}
function handleMouseMove(e){
if(!isDown){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// Put your mousemove stuff here
ctx.beginPath();
ctx.moveTo(startX,startY);
ctx.lineTo(mouseX,mouseY);
ctx.stroke();
startX=mouseX;
startY=mouseY;
}
body{ background-color: white; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4 id='results'>Sign by dragging</h4>
<canvas id="canvas" width=300 height=300></canvas>
[ Addition based on additional question ]
In addition to the signature there could be 2 initials some where on
the contract...How would you hand that?
That involves set recognition through establishing a bounding box.
Find the row containing the topmost opaque pixel,
Move downward by row until you have sufficient rows with no opaque pixels (== until you're sure the signature is vertically complete).
Find the column containing the leftmost opaque pixel,
Move rightward by column until you have sufficient rows with no opaque pixels (== until you're sure the signature is horizontally complete).
The bounding box of the signature is the left/right and top/bottom pixels determined in #1-4.
Erase the pixels in the bounding box.
At this point you've successfully captured the first signature (or initials).
Repeat steps #1-6 until you find no pixels (== until there are no more signatures or initials).
Good luck with your project!