HTML Canvas Zooming Issue - javascript

Recently, I decided to delve into the world of HTML5 and the canvas and I have run into an issue that I cannot figure out how to solve.
I am using the zoom technique that was mentioned in this question, as I need to be able to zoom into a specific point.
However, the issue I have encountered is when you zoom into an area, and then perform a large mouse movement, and then zoom out. The entire viewpoint and objects become skewed. (Objects that were previously occupying the entire canvas, are now partially or sometimes not visible at all.)
I am assuming that the zoom in towards a point function is using the mouse position upon zooming out, which is causing these issues.
Here is a demo to get an idea of the issue: (again to reproduce, just zoom in move the mouse a reasonable distance and zoom out)
Not-Working Demo

This is working as designed. When you apply your context translation based on the mouse position it will zoom centered on that position.
To achieve the fixed zoom out behavior I think you want you need to set the mouseX and mouseY only on zoom in and then use the last mouseX/mouseY (or possibly the center of the canvas, or some point in between) for zoom out.
Updated JSFiddle

Related

how to trigger a function whenever the mouse on screen

I'm being stuck in a problem
I'm creating something like this: https://www.fariasviolins.com/
My English is not good :3
Specifically, I'm creating a infinity layout, the layout will be moved according to the mouse position(The larger the position, the greater the speed), it means that when the mouse to directions, the layout will be moved. I have tried mousemove and it worked, but I also want the layout still move whenever the mouse on screen(even when the mouse not moving, the the speed will calculate by the position of the mouse), I have tried mouseover, but it didn't work as I expected. please help me huhuhuhhu, thank you so much
I think mousemove is the right way to go!
On the example website you mentioned, it looks like the speed depends on the distance between your mouse and the center of the page.
If you calculate the speed that way, the speed shouldn't change if you don't move your mouse. (Because the distance between your mouse and the center of the page doesn't increase either.)

How to make an Infinite Html5 Canvas which can be zoomed and panned?

I was working on a real time whiteboard.
I want to create an Infinite canvas, which can be zoomed using the mouse wheel and panned using drag, using javascript.During the zoom and pan the items drawn on the canvas must also be affected. Is there a was to achieve this without using any external library?
Yes, but it'll take a bit of work. The general idea of what you'll do is the following:
You will need to keep track of the position of the "camera", as well as how close it is to the content - a zoom factor
You will need to attach event listeners to different mouse actions to cause the camera's state to change
When you drag or zoom, you will need to redraw your canvas with the new positions and sizes of all the content. Some math will have to be done to know what the new canvas content is.
There may or may not be certain performance issues you have to address if there's a lot of content on the canvas.
An alternative, possibly quicker approach, but maybe less powerful, would be to not use canvas, and use some CSS magic instead with plain HTML. The basic concept here is that you'll have a 0x0 div as your plane. That div will contain your content, which may include content such as custom SVGs. Each of its children will break out of the div, and will be positioned relative to it. When you drag, you just move the div (through transform: translate()). When you zoom, you just scale the div (through transform: scale()).
Some useful references if taking the second approach:
CSS transform - to move and scale the whiteboard
CSS position - to position content on the whiteboard, and for the general layout
CSS overflow - to crop the whiteboard
The canvas element itself won't be infinite, I guess that's clear enough. What will change when you drag and zoom is the mapping of the real coordinates of your whiteboard elements to the drawing coordinates on the canvas. There's some work to do with detecting the mouse events and doing the calculations for updating the mapping, so there are too many specifics to really put in an answer. But yes of course this is possible without an external library.
Basically canvas could not be set to infinite sized. All you can do is to draw the portion that should be visible in the canvas.
first of all you should store all the points you have drawn to an array.
whenever you pan your canvas , track the offset that you have panned. this offset values can be used to reposition your stored points in your canvas.
eg. suppose you have drawn a line from (50 , 50) to (100 , 100).
let the offsets be {x:0 , y:0}
x , y offsets shows how much x and y distances you have panned in total
then update the points by adding the offsets and redraw
https://github.com/TomHumphries/InfiniteCanvasWhiteboard
here is a simple html5 whiteboard created by Tom Humphries which has infinite zoom and pan.

How to hover areas with XY coordinates shift in MapboxGL JS?

I use hover tooltips in my map. When an area is hovered, I show a tooltip with a small XY shift to the top left corner so that the pointer of the tooltip is not covered by the mouse cursor.
When I move mouse cursor to another area, near its border, like show in the image, the area is highlighted which is under the cursor, not under the square pointer as should be.
What are options to fix this issue? In the ideal way, I would like hover effect to be applied not to the mouse cursor coordinates, but to the coordinates of some other point that is known and changes while mouse is moving.
I once had a similar problem that I tried to solve with a different approach. I wanted to calculate the centroid of the polygon and always place the marker (in your case square pointer) on the calculated position once the user hovers over the polygon.
Main problem I had was that my polygons were concave and had holes in them (you will have the same problem if you are working with country borders) so I found a good algorithm (library) that I used to do this called Polylabel.
You can read more on this topic and how the guys from MapBox used it to solve their label positioning problems on this link.
Although this is not the answer to your question I found that this solution is fast and usable but only if the relation between the zoom level and polygon surface makes sense.
If I wanted to do something like you are suggesting I would first have a default point offset and if that offset goes outside the polygon I would find the nearest point in the polygon coordinates and attach it to that point.
To do these calculations you can use turf.js library. It has the function to return boolean value if the second geometry is completely contained by the first geometry and others that can help you to find the nearest point on the polygon border. I hope this helps!

threejs TrackballControls - Rotate around picked point & Zoom in direction of mouse

I am using threejs (r73). I use a PerspectiveCamera. My goal is to implement mouse interaction. For that purpose I want to use
TrackballControls.js . But I want a slightly different behaviour.
I want to rotate around the point that the user picked on the screen
I want to zoom in direction of the mouse position
For the second point I already found a "solution" at stackoverflow. The zoom works, but when I change the target vector of the control, panning and rotating does not work any longer.
Can anyone provide such an modified implementation of TrackballControls or help me with that?
EDIT
With the applied "solution" panning still works but rotating doesn't.
The idea from https://stackoverflow.com/a/16817727/2657179 also does not work.

Build roulette using jQuery and CSS3 rotation

I'm trying to build a roulette to be controlled by the mouse, I'm not using canvas or svg but only CSS3 rotation and some jQuery.
What I want to achieve is when the mouse is over the roulette and he is clicked and holds down, I want the user to be able to rotate the wheel when he moves the mouse up and down.
I'm using the event.offsetY to get the position of the mouse and according to this position I'm moving the roulette with or against the clock.
The problem is that I think the mouse offset position is changing according to the rotation of the wheel, is their a way to keep the mouse offset position "real" with the document?
-Or-
Someone know a better idea to accomplish that?
Please see the code here: http://jsfiddle.net/MZxgp/ (works on chrome only)
Many thanks!
I used a overlay div that doesn't move to capture the mouse events (see jsFiddle)
I hope this helps

Categories

Resources