Canvas render line on top of the SVG map having issue - javascript

I'm trying to draw a line when clicking on SVG path element. However, I'm having an issue with z-index. As you can see, the canvas is not on the top of the path element.
I'm expecting this to be like this:
I've tried to change z-indexes on the map and canvas itself with no luck. Is there any way to achieve this? All of SVG's path elements must be clickable at the same time.
Here's the: full code
document.querySelectorAll("g").forEach(function(path) {
path.addEventListener("click", function(pointer){
var circle = document.querySelector(".map-tooltip-circle");
circle.style.top = pointer.offsetY - 12 + "px";
circle.style.left = pointer.offsetX - 11 + "px";
circle.style.transform = "scale(1)";
drawCanvas(pointer.offsetX, pointer.offsetY, 590, 370);
});
});

Related

How can I maintain accurate rectangle hover detection after scaling a canvas?

I am writing an application that draws rectangles on a HTML canvas using the fillRect function. I currently track the movement of the mouse and detect when the mouse pointer hovers over a rectangle to highlight it:
This is how I am currently detecting collision which works great.
//boxes2 is my array of rectangles
var l = boxes2.length;
for (var i = l - 1; i >= 0; i--) {
if (mouseX >= boxes2[i].x && mouseX <= (boxes2[i].x + boxes2[i].w ) &&
mouseY >= boxes2[i].y && mouseY <= (boxes2[i].y + boxes2[i].h )) {
selectedBoxNum = i;
}
}
My problem is that this hover detection no longer works well after zooming in/out as the actual bounds of the rectangles desync from their values in my rectangle array.
var currentZoomValue = 1;
function myOnMouseWheel(event) {
event.preventDefault();
// Normalize wheel to +1 or -1.
var wheel = event.wheelDelta / 120;
if (wheel == 1) {
zoom = 1.1;
}
else {
zoom = .9;
}
currentZoomValue = currentZoomValue * zoom
canvas.style.transform = "scale(" + currentZoomValue + ")";
}
What I have tried:
Scaling the values in the array as I zoom in/out so that the rectangle bounds will stay in sync
This will not work for me because the scale function is stretching my canvas to make the rectangles look bigger. If I also actually make them bigger, they will be doubly enlarged and outpace the zoom of my canvas background.
Compensating my hover detection based upon my current zoom level
I have tried something like:
if (mouseX >= boxes2[i].x && mouseX <= (boxes2[i].x + (boxes2[i].w * currentZoomValue) ) &&
mouseY >= boxes2[i].y && mouseY <= (boxes2[i].y + (boxes2[i].h * currentZoomValue) )) {
selectedBoxNum = i;
}
My attempts at this do not work because while the rectangle height and width do scale in an easily predictable way, the x,y coordinates do not. When zooming in, the rectangles will radiate out from the center so some rectangles will gain x value and other lose based upon their position. I also considered maintaining a second rectangle array that I could use just for hover detection but decided against it for this reason.
A good solution would be to actually scale the rectangle's sizes to give the illusion of zooming, but the rectangles positions on the background image is important, and this technique will not affect the background.
Since there is no standard way of knowing page zoom level, I would suggest catching the click event with an absolutely-positioned div.
You can get the offset of your canvas element with the getBoundingClientRect() method.
Then, the code would look something like this:
boxes2.forEach(function(box, i) {
cx.fillRect(box.x, box.y, box.w, box.h);
/* We create an empty div */
var div = document.createElement("div");
/* We get the position of the canvas */
var rect = canvas.getBoundingClientRect();
div.style.position = "absolute";
div.style.left = (rect.left + box.x) + "px"; //Don't forget the pixels!!!
div.style.top = (rect.top + box.y) + "px";
div.style.width = box.w + "px";
div.style.height = box.h + "px";
/* For demonstration purposes we display a border */
div.style.border = "1px dashed black"
div.onclick = function() {/* Your event handler */}
document.body.appendChild(div);
});
Here's a live demonstration. At least in my browser, regions stay consistent even if I zoom in and out the page.

How to align HTML span at center of highchart donut graph with responsive design?

I am using Highcharts.js for drawing a do-nut graph.
Here i need legends just right to graph and a 'span' outside the container(svg) on the center of graph. Legends work properly, while 'span' doesn't align at the center of graph on responsive view.
JSFIDDLE
var chartDiv = document.getElementById('container');
var textX = $(chartDiv).width()/2;
var textY = $(chartDiv).height()/2 ;
var span = '<span id="pieChartInfoText" style="position:absolute;text-align:center;">';
span += '<span class="centerText">'+Math.round((response.engagement / response.traffic || 0) * 100) + '%</span><br></span>';
$("#addText").append(span);
span = $('#pieChartInfoText');
span.css('left', textX + (span.width() * -0.5));
span.css('top', textY + (span.height() * -0.5));
there are a few things going wrong here but the main thing ist this: the circle is actually not in the center of the screen, so the text is but the circle is not you need to adjust the text position to that of the circle offest. plus body has a margin and is not 100% height
also this part here sets the height and the width so we can then calculate the percentage offset
var $addText = $("#addText");
$addText.append($span)
.height($addText.height())
.width($addText.width());
see this solution
http://jsfiddle.net/zgLm44q5/1/
also I optimised you code a bit, but there are still thing that could be written more elegantly
I have fixed the issue by using chart 'load' callback.
Refer here
events: {
load: function() {
var chart = this,
rend = chart.renderer,
pie = chart.series[0],
left = chart.plotLeft + pie.center[0],
top = chart.plotTop + pie.center[1],
text = rend.text(Math.round((response.engagement / response.traffic || 0) * 100) + '%', left, top).attr({'text-anchor': 'middle','class': 'middleText'}).add();
}
}
JSFIDDLE

Mapping Coordinates of One DIV to Another DIV

am having 2 divs with different height and width having image as background.
my requirement is to get the cropped coordinates of one div, and position that coordinates to another div.. i need the coordinates..
how can i do that.
Have a look at getBoundingClientRect()… Note that you need to take care of the parent Nodes. If the parents of the div elements have diffrent positions, than you need to take this difference into accout.
The code below assumes that both divs have the same parent and are positioned absolute.
var bbox = div1.getBoundingClientRect();
div2.style.top = bbox.top + 'px';
div2.style.left = bboox.left + 'px';
div2.style.width = bbox.right - bbox.left + 'px';
div2.style.height = bbox.bottom - bbox.top + 'px';

Getting the right position of an IMG and calculating the distance to right side of screen

I have been trying to find a solution to a problem I have.
My website has different thumbnails on it and I added a onmouseover / onmouseout function. So if you move your mouse over a picture, a hover image (the original size) is shown in the upper right corner.
This all works fine, but if I have bigger image, it will overlap my thumb img and stuff gets crazy.
So what I wanted was to get the right side position of my thumbnail IMG tag and subtract that from the screen size. The screen size is not a problem, but the right position of my img tag is.
How could i get that position? (marked with bold red line in pic)
The code looks something like this:
function imghover(id, src, width, height) {
var thumb = document.getElementById(id);
var hover = document.getElementById('hoverimg');
alert(thumb.
hover.src = src;
if(width > screen.width){
hover.width = (width / 100) * 20;
hover.height = (height/ 100) * 20;
}
else if(height > screen.height) {
hover.width = (width / 100) * 40;
hover.height = (height/ 100) * 40;
}
else {
hover.width = width;
hover.height = height;
}
}
As you can see i have everything I need: Thumb ID, scr for new pic (original), width & height of original. So how to get the right side position of the Thumb?
Thanks a lot in advance.
right is usually calculated as
right = totalScreenWidth - left - sizeOfBox(or what ever detail you wand to + -);
The equation is followed in a relative way .. say for example the whole thing is in a div container rather than in window.
You can get left for image like ..
totalLeft = image.getBoundingClientRect().left + imageParent.getBoundingClientRect().left + .... cascadingly .. till you cover each element from image to window.
or use jquery to use it like $(#img).position().left .. etc
Here is the code for your problem: http://jsfiddle.net/B24QL/
You can view the preview here : http://jsfiddle.net/B24QL/embedded/result/
jQuery
$(document).ready(function(){
var a = $('img').offset().left + $('img').width(),
b = $(window).width() - a;
alert("Position of right border of image: " + a + "px from left edge.\n Distance between right border and image = " + b + "px.");
});

Html Canvas Resizing And Coordinate Space

Note: I'm using Google Chrome
Currently I have this test page
http://www.evecakes.com/doodles/canvas_size_issue.htm
It should draw a rectangle right below the mouse cursor, but there are some really weird scaling issues which is causing it to draw at a varying offset. I think it's because the canvas coordinate space is not increasing along with its html size. Is there a way to increase that coordinate space size?
Here's the javascript function
$('#mapc').mousemove(function (event) {
var canvas = $('#mapc');
var ctx = canvas[0].getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(event.clientX, event.clientY, 55, 50);
document.title = event.clientX + " --- " + event.clientY;
});
Set the width and height HTML attributes of the canvas. Right now, it's assuming its default width and the CSS is just stretching it, and it appears as if it is scaling.
A side-note, you can use this in the mousemove event - it is a reference to #mapc element, so you won't have to query the DOM on every mouse move.
var offset = $('#mapc').offset();
$('#mapc').mousemove(function (event) {
var ctx = this.getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(event.pageX - offset.left, event.pageY - offset.top, 1, 1);
});

Categories

Resources