HTML5 Canvas - Context Sensitive Menu - html

I'm drawing a number of rectangles on an HTML5 canvas and want to be able to right click on the boxes and get a context sensitive menu displayed. The menu should be specific to the type of box being clicked on and be totally user specified, i.e. it should not include Reload, Save As, Print etc...
Can any one give me any pointers?
Thanks,
Paul

You can addEventListener for context menu to handle right-mouse requests:
// listen for contextmenu requests
canvas.addEventListener('contextmenu', handleContextmenu, false);
Then in the handler, you check each of your rects for hits:
function handleContextmenu(e){
// get mouse position relative to the canvas
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
// check each rect for hits
for(var i=0;i<rects.length;i++){
var rect=rects[i];
var rectRight=rect.x+rect.width;
var rectBottom=rect.y+rect.height;
// if this rect is hit, display an alert
if(x>=rect.x && x<=rectRight && y>=rect.y && y<=rectBottom ){
alert("Context menu request on the "+rect.color+" rectangle.");
}
}
// prevents the usual context from popping up
e.preventDefault()
return(false);
}
Here is working code (no jsFiddle because no right-clicking in X-Domain iframes):
<!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 canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var rects=[];
rects.push({x:50,y:50,width:50,height:50,color:"red"});
rects.push({x:150,y:100,width:75,height:75,color:"blue"});
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<rects.length;i++){
var rect=rects[i];
ctx.beginPath();
ctx.fillStyle=rect.color;
ctx.rect(rect.x,rect.y,rect.width,rect.height);
ctx.fill();
}
// listen for contextmenu requests
canvas.addEventListener('contextmenu', handleMouseDown, false);
function handleMouseDown(e){
// get mouse position relative to the canvas
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
// check each rect for hits
for(var i=0;i<rects.length;i++){
var rect=rects[i];
var rectRight=rect.x+rect.width;
var rectBottom=rect.y+rect.height;
// check each rect for hits
if(x>=rect.x && x<=rectRight && y>=rect.y && y<=rectBottom ){
alert("Context menu request on the "+rect.color+" rectangle.");
}
}
// prevents the usual context from popping up
e.preventDefault()
return(false);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Related

Here maps not draggable in ms access webbrowser

I have created a simple html using the draggable marker example from here maps. I have adapted it to support IE 11 by adding reference to legacy js, meta tag and using P2D engine in map options. Also added two url parameters for coordinates. It works perfectly in IE11 and it loads and shows pan and zoom buttons in ms-access webbrowser but it keeps static, it's not draggable, but pan and zoom works.
The curious thing is that if I navigate to wego.here.com in the same webbrowser control then the map is draggable. So they're doing something else in the here maps main page that I'm not doing in my script.
I have also tried using Microsoft Web Browser from the activex controls list in access.
I need it to be draggable so I can pick the coordinates after the user changes the marker position.
This is my script:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Draggable Marker</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-core.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-core-legacy.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-service-legacy.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js" type="text/javascript" charset="utf-8"></script>
<script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js" type="text/javascript" charset="utf-8"></script>
<style>
html, body { margin:0px; padding:0px; width: 100%; height: 100%; }
.main { height: 100%; }
</style>
</head>
<body id="markers-on-the-map">
<div class="main" style="width:100%" id="map"></div>
<input type="hidden" id="long" name="long">
<input type="hidden" id="lat" name="lat">
<script>
function addDraggableMarker(map, behavior){
var marker = new H.map.Marker({lat:latitud, lng:longitud}, {volatility: true});
// Ensure that the marker can receive drag events
marker.draggable = true;
map.addObject(marker);
// disable the default draggability of the underlying map
// and calculate the offset between mouse and target's position
// when starting to drag a marker object:
map.addEventListener('dragstart', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
var targetPosition = map.geoToScreen(target.getGeometry());
target['offset'] = new H.math.Point(pointer.viewportX - targetPosition.x, pointer.viewportY - targetPosition.y);
behavior.disable();
}
}, false);
// re-enable the default draggability of the underlying map
// when dragging has completed
map.addEventListener('dragend', function(ev) {
var target = ev.target;
if (target instanceof H.map.Marker) {
$('#long').val(ev.target.b.lng);
$('#lat').val(ev.target.b.lat);
behavior.enable();
}
}, false);
// Listen to the drag event and move the position of the marker
// as necessary
map.addEventListener('drag', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
if (target instanceof H.map.Marker) {
target.setGeometry(map.screenToGeo(pointer.viewportX - target['offset'].x, pointer.viewportY - target['offset'].y));
}
}, false);
}
/**
* Boilerplate map initialization code starts below:
*/
//Step 1: initialize communication with the platform
// In your own code, replace variable window.apikey with your own apikey
var platform = new H.service.Platform({
apikey: '?????????????????????????????????'
});
var defaultLayers = platform.createDefaultLayers();
//url parameters
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = decodeURIComponent(pair[1]);
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]],decodeURIComponent(pair[1]) ];
query_string[pair[0]] = arr;
} else {
query_string[pair[0]].push(decodeURIComponent(pair[1]));
}
}
var latitud=query_string.lat;
var longitud=query_string.long;
//Step 2: initialize a map - this map is centered over Boston
var map = new H.Map(document.getElementById('map'),
defaultLayers.raster.normal.map, {
center: {lat:latitud, lng:longitud},
engineType: H.map.render.RenderEngine.EngineType.P2D,
zoom: 12,
pixelRatio: window.devicePixelRatio || 1
});
// add a resize listener to make sure that the map occupies the whole container
//window.addEventListener('resize', () => map.getViewPort().resize());
window.addEventListener('resize', function () {map.getViewPort().resize(); });
//Step 3: make the map interactive
// MapEvents enables the event system
// Behavior implements default interactions for pan/zoom (also on mobile touch environments)
//var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
// Step 4: Create the default UI:
var ui = H.ui.UI.createDefault(map, defaultLayers, 'en-US');
// Add the click event listener.
addDraggableMarker(map, behavior);
</script>
</body>
</html>```
Check please on this static page
: your code works for my IE11

Enable and disable mouse events for canvas using Fabric.js

I am using Fabric.js to draw rectangles on a canvas. After drawing a rectangle, I want to disable all events on that object. I have tried to do it using canvas.__eventListeners["mouse:down"] = []; but then after the object selection is cleared, the canvas can't apply any events.
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 canvas - Image color picker | Script Tutorials</title>
<link href="index.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js" ></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<div class="column1">
<canvas id="panel" width="700" height="350"></canvas>
</div>
<div style="clear:both;"></div>
<div id="log"></div>
</div>
</body>
<script>
(function() {
var canvas = new fabric.Canvas('panel');
var clicks=0;
var x1=0;var y1=0;
var rect;
canvas.on('mouse:down', function(e){
//check if you clicked on an object that exists canvas
if(e.target == undefined){
if (clicks == 0) {
var pointer=canvas.getPointer(event.e);
console.log(pointer);
x1 = pointer.x;
y1 =pointer.y;
console.log("Start Pointer " +x1 ,y1);
clicks++;
}
else
{
var endpointer=canvas.getPointer();
console.log(endpointer);
var endx=endpointer.x;
var endy=endpointer.y;
console.log("Endpointer " +endx ,endy);
console.log("x and y"+x1,y1);
var newwidth=endpointer.x- x1;
var newheight=endpointer.y - y1;
rect=new fabric.Rect({
left:x1,
top: y1,
originX :'left',
originY :'top',
width:newwidth,
height:newheight,
selectable: true,
evented:false,
fill:'red',
opacity :0.3
});
canvas.add(rect);
//console.log(rect.setWidth(pointer2.x- x1 ));
//console.log(rect.setHeight( pointer2.y - y1));
canvas.renderAll();
clicks=0;
}
}
else
{
//canvas.getActiveObject().remove();
canvas.__eventListeners["mouse:down"] = [];
}
});
canvas.on('object:moving',function(){
var bound=rect.getBoundingRect();
console.log(bound.left,bound.top,bound.width,bound.height);
});
canvas.on('object:scaling',function(){
var bound=rect.getBoundingRect();
console.log(bound.left,bound.top,bound.width,bound.height);
});
canvas.on('object:selected',function(e){
document.onkeydown = function(e) {
if (e.keyCode === 27||e.button==3) {
e.preventDefault();
canvas.getActiveObject().remove();
}
}
});
fabric.Image.fromURL('fedex.jpg', function (img) {
canvas.add(img.set({
width: 700,
height:350,
left: 350,
top: 175,
selectable: false,
}));
});
})();
</script>
With the method canvas.off('mouse:down', eventHandler) event handlers registered using canvas.on('mouse:down', eventHandler) can be removed. Be sure to pass the same function into both calls (e.g. by assigning the handler to a variable).
This method is available on all Observables in fabric (see API doc: http://fabricjs.com/docs/fabric.Observable.html#off)
What is the final answer? We're basing our decision to mousedown on or mousedown off, based on the event - if it has a target. I came up with this solution (a 2nd mousedown handler), but it didn't work.
canvas.on('mouse:down', function (e) {
// canvas click, not object click; so create the obj
if (e.target === undefined) {
canvas.on('mouse:down', eventHandler);
}
else {
// an object was clicked, so don't create the obj again
canvas.off('mouse:down', eventHandler);
}
});
Where eventHandler is the function that handles object creation.

How to execute a function on mouse click on rectangle HTML5 Canvas

I'm looking for a simple way to execute a function when someone clicks on a rectangle inside an HTML5 Canvas. I would like to do it in a way that doesn't require any special libraries. Any suggestions?
Here's a no-library way which involves:
Listening for mousedown events:
var canvas=document.getElementById("canvas");
canvas.onmousedown=handleMousedown;
Testing if the clicked mouse position is inside the rectangle:
var rect={x:100,y:100,w:75,h:40};
// mx & my are the mouse coordinates
if(mx>=rect.x && mx<=rect.x+rect.w && my>=rect.y && my<=rect.y+rect.h){
alert("clicked in rect");
}
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var BB,BBoffsetX,BBoffsetY;
setBB();
var rect={x:100,y:100,w:75,h:40};
ctx.fillRect(rect.x,rect.y,rect.w,rect.h);
canvas.onmousedown=handleMousedown;
function handleMousedown(e){
e.preventDefault();
e.stopPropagation();
var mx=e.clientX-BBoffsetX;
var my=e.clientY-BBoffsetY;
if(mx>=rect.x && mx<=rect.x+rect.w && my>=rect.y && my<=rect.y+rect.h){
alert("clicked in rect");
}
}
function setBB(){
BB=canvas.getBoundingClientRect();
BBoffsetX=BB.left;
BBoffsetY=BB.top;
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4>Click in the rect for an alert</h4>
<canvas id="canvas" width=300 height=300></canvas>

Html graphics rendering control like the BitBucket one

I'm trying to find out what graphics library is BitBucket using to create the visualization of the commit graph (the lines on the left), if it's public.
If the library used by BitBucket is not available open source or commercially, what would be some alternative HTML 5 based libraries can be used to achieve similar effects ?
This is not for a VCS system but for other kind of project
Here's code to draw the primitives in the commit graph:
lines: that curve into columnar tracks
branches: that split a single line into 2
dots: representing events
A Demo: http://jsfiddle.net/m1erickson/cz37L/
Example 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 ctx=canvas.getContext("2d");
ctx.lineWidth=2;
var offsetX=20;
var offsetY=10;
var spacingX=12;
var spacingY=25;
var y=0;
// lines
var lines=[];
lines.push([0,0,0,0,1,1,2,2,2,2,2,2,2,2,2,2,3]);
lines.push([1,1,1,1,2,2,3,3,3,3,3,3,3,3,3,3,4]);
lines.push([2,2,2,2,3,3,4,4,4,4,4,4,4,4,4,4,5]);
lines.push([3,3,3,3,4,4]);
lines.push([4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5]);
lines.push([5,5,5,5]);
var branches=[];
branches.push({line:2,x1:4,y1:5,x2:4,y2:4});
branches.push({line:3,x1:5,y1:2,x2:4,y2:3});
branches.push({line:4,x1:5,y1:6,x2:4,y2:5});
branches.push({line:4,x1:5,y1:14,x2:4,y2:13});
// dots
var events1=[5,5,5,4,4,4,5,4,4,4,4,4,4,4,5,5];
var events2=[5,5,5,3,3,2,4,2,2,2,2,2,2,2,4,2];
var colors=["purple","olive","cyan","magenta","khaki","green"];
drawAll();
function drawAll(){
for(var i=0;i<lines.length;i++){
drawLine(lines[i],colors[i]);
}
for(var i=0;i<branches.length;i++){
drawBranch(branches[i],colors[branches[i].line]);
}
for(var i=0;i<events1.length;i++){
ctx.beginPath();
ctx.arc(offsetX+events1[i]*spacingX,offsetY+i*spacingY,3,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=colors[events2[i]];
ctx.fill();
}
}
function drawBranch(branch,linecolor){
var x1=offsetX+branch.x1*spacingX;
var x2=offsetX+branch.x2*spacingX;
var y1=offsetY+branch.y1*spacingY;
var y2=offsetY+branch.y2*spacingY;
var cy=cy2=y1+(y2-y1)/2;
ctx.beginPath();
ctx.moveTo(offsetX+branch.x1*spacingX,offsetY+branch.y1*spacingY);
ctx.bezierCurveTo(x1,cy,x2,cy,x2,y2);
ctx.strokeStyle=linecolor;
ctx.stroke();
}
function drawLine(line,linecolor){
var y=0;
ctx.beginPath();
ctx.moveTo(offsetX+line[0]*spacingX,offsetY+y*spacingY);
for(var i=1;i<line.length;i++){
if(line[i]==line[i-1]){
ctx.lineTo(offsetX+line[i]*spacingX,offsetY+y*spacingY);
}else{
var x1=offsetX+line[i-1]*spacingX;
var x2=offsetX+line[i]*spacingX;
var y1=offsetY+(y-1)*spacingY;
var y2=offsetY+y*spacingY;
var cy=cy2=y1+(y2-y1)/2;
ctx.bezierCurveTo(x1,cy,x2,cy,x2,y2);
}
y++;
}
ctx.strokeStyle=linecolor;
ctx.stroke();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=400></canvas>
</body>
</html>

HTML 5 and images map

Anyone knows how to accomplish such a thing
http://www.jarzebinowe.pl/mieszkania.html (you need to choose floor ...)
in html5?
It's about choosing the apartment, lights, etc. ..
Top how would one image was processed by HTML5 so that was the result
I'm sorry for being so strange and laconic question
Try the html map element
You probably can achieve your "drill-down" into a building more simply by using html map which will let your users click on a portion of an image and link to a new more specific image.
Here's a reference: http://www.w3schools.com/tags/tag_map.asp
[Edit with a fancier display with canvas.]
Here's code and a Fiddle: http://jsfiddle.net/m1erickson/BbCJx/
<!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; padding:15px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var floorplan=document.getElementById("floorplan");
var planCtx=floorplan.getContext("2d");
planCtx.font="24px Arial";
planCtx.fillStyle="red";
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var lastWindow=-1;
var plan=new Image();
var outside=new Image();
outside.onload=function(){
plan.onload=function(){
ctx.drawImage(outside,0,0);
}
plan.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/inside.jpg";
}
outside.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/outside.png";
var windows=[]
windows.push({top:66, left: 70, bottom:111, right:111, floorplan:0, apartment:"3a"});
windows.push({top:66, left:139, bottom:111, right:183, floorplan:0, apartment:"3b"});
windows.push({top:66, left:211, bottom:111, right:255, floorplan:0, apartment:"3c"});
windows.push({top:153, left: 70, bottom:196, right:111, floorplan:1, apartment:"2a"});
windows.push({top:153, left:139, bottom:196, right:183, floorplan:1, apartment:"2b"});
windows.push({top:153, left:211, bottom:196, right:255, floorplan:1, apartment:"2c"});
windows.push({top:239, left:139, bottom:283, right:182, floorplan:2, apartment:"1a"});
function selectWindow(x,y){
var w;
var isInWindow=false;
for(var i=0;i<windows.length;i++){
w=windows[i];
if(x>w.left && x<w.right && y>w.top && y<w.bottom){
isInWindow=true;
if(i!=lastWindow){
planCtx.clearRect(0,0,floorplan.width,floorplan.height);
planCtx.drawImage(plan,0,0);
planCtx.fillText("Apt: "+w.apartment+", Plan: "+w.floorplan,70,25);
lastWindow=i;
}
break;
}
}
if(!isInWindow){ planCtx.clearRect(0,0,floorplan.width,floorplan.height); };
}
function handleMouseMove(e){
canMouseX=parseInt(e.clientX-offsetX);
canMouseY=parseInt(e.clientY-offsetY);
$("#movelog").html("Move: "+ canMouseX + " / " + canMouseY);
// Put your mousemove stuff here
selectWindow(canMouseX,canMouseY);
}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
}); // end $(function(){});
</script>
</head>
<body>
<p>Mouse over a window to see it's floorplan</p>
<canvas id="canvas" width=300 height=300></canvas>
<canvas id="floorplan" width=300 height=300></canvas>
</body>
</html>