OpenSeadragon zoom issues - javascript

I am trying to learn openseadragon zoom functionality, however, not understanding something. I put together a simple example and have few questions:
https://codepen.io/Ivalina/pen/poPbaMv
When page first loads, how can I make sure that when I click zoom out right away, image doesn't get any smaller than it already is. This is confusing, as I would hope it starts at its smallest. (priority)
Another question, I did set the min and max zoom levels, yet when I keep on clicking zoom in, it definitely goes beyond 3 clicks. Same goes for zoom out once zoomed in. Is there a way to limit zoom to specific amount of clicks (preferably 3).
var tileSources = {
Image: {
xmlns: "http://schemas.microsoft.com/deepzoom/2008",
Url: "//openseadragon.github.io/example-images/duomo/duomo_files/",
Format: "jpg",
TileSize: "256",
Size: {
Width: "13920",
Height: "10200"
}
}
};
var viewer = OpenSeadragon({
id: "seadragonviewer",
prefixUrl: "//openseadragon.github.io/openseadragon/images/",
tileSources: tileSources,
visibilityRatio: 1.0,
constrainDuringPan: true,
minZoomLevel: 0,
maxZoomLevel: 2,
zoomPerClick: 1.5,
gestureSettingsMouse: {
clickToZoom: false,
scrollToZoom: false,
flickEnabled: true
},
gestureSettingsTouch: {
clickToZoom: false
},
visibilityRatio: 1.0,
useCanvas: false
});

This isn't necessarily an answer, per se, but I need more space than a comment, so here goes:
The OSD "zoom" is based on the relationship between the width of the image and the width of the viewer. It is 1 when the image exactly fills the viewer horizontally. If you zoom in enough that the viewer only shows half of the width of the image, the zoom is 2. Zoom in enough that the viewer can only hold a quarter of the width, and the zoom is 4. The maxZoomLevel option is based in those terms.
By default, the furthest you can zoom in is based on the ratio of image pixels to screen pixels specified in the maxZoomPixelRatio option (default 1.1). In other words, if maxZoomPixelRatio is 1, then you can only zoom in enough to see the image pixels 1:1. As you've found, you can override that with maxZoomLevel, but then how close to the actual pixels you can get will depend on the size of your viewer.
At any rate, if what you want is to guarantee three clicks and you don't care about how close you get to the actual pixels, here's a scenario:
If your image naturally fills the viewer on the horizontal dimension, you'll get a starting zoom of 1. If zoomPerClick is set to 2, on the first click your zoom will now be 2. On the second click it'll be 4 (zooms are multiplicative), and on the third zoom it'll be 8. Therefore you should set your maxZoomLevel to 8 in that scenario.
If your image doesn't start with a zoom of 1 (because it's tall enough it doesn't fill out the width of the viewer), you'll have to base the maxZoomLevel on that starting zoom. If you have a different zoomPerClick, you'll have to take that into account.
If you do care about how close to the actual pixels you can get on the third click, you'll need to adjust your zoomPerClick so it's different for every viewer size/image size ratio.
I hope this additional background info helps!
EDIT: here's how you might set the zoomPerClick:
What you need to know is the home zoom (where the user starts with the image zoomed all the way out) and the full zoom (when you're zoomed all the way in to see the pixels of the image 1:1), and then you need to figure out what you have to multiply the home zoom by 3 times (since you want 3 clicks) in order to get to the full zoom. Fortunately you can do this after the image is loaded, so OpenSeadragon can do most of the math for you.
viewer.addHandler('open', function() {
const homeZoom = viewer.viewport.getHomeZoom();
const fullZoom = viewer.viewport.imageToViewportZoom(1);
viewer.zoomPerClick = Math.cbrt(fullZoom / homeZoom);
});
I haven't tested this code, but it should be the basic idea.

Related

vis.js network - is there a setting to make the node labels stay the same size on zoom?

Basically the title. The client is complaining that when he zooms in, the text labels for the nodes are quite large. Is there a way to keep the node labels at a fixed font size even when zooming in or out?
From the nodes documentation (http://visjs.org/docs/network/nodes.html), there's a scaling.label option, but it doesn't seem to work. I think this is only relevant if I'm using values to scale the nodes.
Here is my implementation:
network.on( "zoom", function(properties){
var options = {
nodes: {
// 1/scale to make text larger as scale is smaller
// 16 is my default font size
font: {
size: ( 1 / network.getScale() ) * 16
}
}
};
network.setOptions(options);
});
As far as I know, there's no such option. The scaling.label option, if I understand correctly what you mean, is used to set a scaling factor, not disable zooming.
However, you can implement this yourself, namely change scaling of labels on zoom. Fortunately, there's zoom event: set a handler like
network.on('zoom',rescaleLabels);
and implement rescaleLabels by setting the corresponding scale factor to their labels. In there, you can use network.getScale() to get new scale and then set scaling of nodes.

Force cropper to always be either full width or full height

I have been using cropper js.
I am resizing the cropper based on input values(integer). For example A and B.
So when user enters A = 200 and B = 240. The cropper calculates the aspect ratio and shows the cropper. Is there a option or some kind of hack to force the cropper to either force it to fill the width or height based on the ratio?
If i was unclear in my question see images below.
First there is an incorrect image where i got spaces on both sides and at the top and bottom.
Incorrect
This image is correct:
Correct
So at the correct image the user shouldn't be able to make it smaller, and if the the ratio get's below 1 in ratio it should fill the height instead of width.
Do someone have a good soultion on this?
I figured it out!
If someone looking for the answer, what i did -->
Set following options to cropper:
viewMode: 2 (not necessarily 2, but needs to be more than 0).
cropBoxMovable: true. (Could only change the cropBox by my inputs.)
dragMode: 'none'. Otherwise the user could drag a new cropBox.
cropBoxResizable: false. OtherWise user could drag in the corners in of crfopbox and change size.

How to recalculate x,y coordinates based on screensize

I'm have a heat map application and store I store the x,y coordinates of a click and also the viewport width and height. Real data for 2 clicks:
x, y, width, height
433, 343, 1257, 959
331, 823, 1257, 959
The issue is when I resize the screen on the responsive site, the displayed clicks are now all off. I'm coming up empty on my searches but is there a formula or algorithm to recalculate the x and y coordinates for different resolutions. For example, the first click, if the width goes from 1257 to 990 and the height goes from 959 to 400, how to I recalculate the x and y so they line up in the same spot?
EDIT:
I added 2 fields to the database, width_percentage and height percentage
to store the x percentage of the width and the y percentage of the height. So if x was 433 and the width of the screen was 1257 then x was 35% from the left edge of the screen. I then used the same theory for the height and ran the calculations but it did not scale the click dot to the same spot as I though the percentages would do for scaling resolutions. I testing this by clicking on full resolution 1257 width then reopening at 900 width. See below for code to display click dots at lower resolution.
Ajax PHP
while ($row = mysql_fetch_array($results)) {
if( $_GET['w'] < $row['width'] ) {
$xcorr = $row['width_percentage'] * $_GET['w'];
$ycorr = $row['y'];
}
}
This uses the $_GET variable, passing the width and height of the screen resolution on page load. Then it gets the click dots from the database as $results. Since I only scale the resolution width from 1257 to 900 I did not put in calculation for height and its the same pixel as the initial click. The new width I multiplied by the percentage and set the dot that percentage margin from the left of the screen. Since the percentage is 35%
the new x coordinate becomes 900 *.35 = 315px from the left edge. It did not work and I'm still scratching my head on head to keep click in the same spot for responsive sites.
Have you tried this mathematical formula to change the range of a number?
And also instead of storing this:
x, y, width, height
433, 343, 1257, 959
331, 823, 1257, 959
You could store it normalized between 0 and 1 so it works for any width/height (calculated by dividing each x by its width and each y by its height):
x, y
0.344, 0.357
0.263, 0.858
Then you don't need to know the width/height you used when you stored them, and when you want to translate them to the size of the current screen you just multiply each one by the current width/height
You can acheive this by jquery:
$( window ).resize(function() {
//ur code
});
javascript
window.onresize = resize;
function resize()
{
alert("resize event detected!");
}
if you are working on mobile devices use this one also
$(window).on("orientationchange",function(event){
alert("Orientation is: " + event.orientation);
});
I think you are on the right track with the percentages. Are you including the offset of the map image. I wonder if your algo is working but the visual representation appears wrong because the offset is changing in the viewport.
$(window).resize(function() {
var offset = yourMap.offset();
myLeft = offset.left();
myTop = offset.top();
});
You need to add the offsets every time to get the proper placement.
This is what you should do. Sometimes the resize event fires when the document is being parsed. It is a good idea to put the code inside an onload event function. The orientation change function is taken from #Arun answer.
window.onload = function() {
$(window).on("orientationchange", function(event) {
alert("Orientation is: " + event.orientation);
});
window.onresize = function() {
alert('window resized; recalculate');
};
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
for this you need to do some calculation. Here is the function which will return new x and y potion based on the height and width
function getNewX(xVlaue, oldWidth, newWidth){
return xVlaue * newWidth / oldWidth;
}
newX = getNewX(10, 150, 100); // Use
You can use the common function for height and width calc.
DEMO
The whole question highly depends on the page you want to use this on.
Most pages have a centered block and/or some self-resizing (read "responsive") elements. If the page is not very responsive, e.g. having a fixed width, you have an easier job. If the page is centered, you might want to save the cursor's X-position relative to the center of the page. this way the window width doesn't matter. The same also applies to left- and right aligned pages of course - in this case you would save the X-pos relative to the left or right edge of the window respectively.
The following image shows a center-oriented click position. Note that the x- and y properties of the click don't change here if you resize the window.
Now to the more generic methods
If you save the window dimensions, the cursor position AND the scroll offsets on every click, you will most probably be able to reproduce it alongside the layout, but you'll need to reproduce it for every unique dimensions set. If you used the trick from above you might be able to overlay all layouts and find a common denominator. For example, if your page is centered in the window, has a max-width, and you saved the X-pos relative to the center of the window, you can overlay all clicks that happened in windows that were at least that width.
You could do some trickery however, and save the clicked elements alongside the informations you already do save. If you also save the click position relative to the element, you can evaluate this data to something like "the submit button is rather pressed on the bottom right side" or "people often click on the far end of that drop-down and sometimes mis-click by a few pixels".
Try both of the following:
1. Padding and margins might not scale. Use "* {padding:0;margin:0}" at the end of your stylesheet and check if that fixes it.
2. Ensure outer and inner (that means all) elements scale. Any single element failing to scale will make many other elements fall out of place. This generally happens with text inputs. Use "*{border:solid 2}" at the end of your stylesheet to visually observe the effect of scaling on each element.
I'm sure your problem will be resolved.

Responsive Absolute Positioning

I am trying to add a hover effect to each speech bubble in the image below that link to a different page when clicked on.
Currently, I am using an image map and whenever an area of is hovered over jQuery changes the whole image to be the appropriate image that has the speech bubble filled in. It kind of works but IE flickers every time a hover happens and the website is responsive so the image map does not scale when the screen size is changed. I've tried using https://github.com/stowball/jQuery-rwdImageMaps too but it doesn't seem to work on a mobile device.
Ideally I'd like to be able to have the speech bubbles be separate images that are positioned correctly when scaled so I can manipulate the speech bubbles easier.
Screenshot
You could go with approach which uses scaled coordinates.
Here's the basic idea:
var coordManager = {
"imageBaseHeight":800,
"imageBaseWidth":800,
"imageID":"myImg",
"baseCoordinateActions" = [
{"x":10,"y":10,"h":100,"w":100, "text": "Mousing over first option"}, // the square you want the mouseover to cover for a given action
{"x":200,"y":200,"h":100,"w":100, "text": "Mousing over first option"}
],
"scaledCoordinateActions" : [], // this should contain the baseCoordinateActions with the scaled values
"init" : function(id, baseHeight, baseWidth)
{
var self=this;
this.imageID=id;
this.imageBaseHeight=baseHeight;
this.imageBaseWith=baseWidth;
var img = document.getElementById(id);
img.onresize =function()
{
// regenerate the scaled coordinates based on the difference between the imageBaseHeight and the current height;
// usually you can get the scale by dividing the imageBaseHeight by the actual height
};
image.onmousemove = function(event)
{
// check the mouse location based on scaled coordinates if it's within the scaled coordinates of any of the scaledCoordinateAction items
// display that scaleCoordinateAction item's text using the current eventX and Y, or do it relative to the coordinateACtion X and Y.
// make sure to check if the bubble is already showing before changing the display: property to avoid flicker.
}
}
};
coordManager.init("imageID", 800,800);

raphael zoom out with grid - infinite paper size

I am attempting to create a simple drawing package using Raphael.
For this example, I have defined a paper with a specific size that has a grid drawn to the edges of the paper . In my actual application, the paper is set to the size of the div.
See the fiddle http://jsfiddle.net/davidbe/LhWZ5/
I'm using the raphael.pan-zoom package to support zooming with the scroll wheel and panning with the left mouse button.
page = Raphael(graph_paper, 402, 602);
panZoom = page.panzoom({ initialZoom: 0,
initialPosition: { x: 0, y: 0},
maxZoom: 30,
minZoom: -10});
panZoom.enable();
This works fine when I zoom in, but the problem I am having is that when I zoom out so that the Raphael paper is smaller than the div, the grid lines do not extend to the edge of the div. I'm trying to figure out a way to have the grid lines always displayed to the edges of the div, regardless of my zoom setting. In order to do this, I think that I either need to define a larger paper size when I create the paper so that when I zoom out, I am still seeing part of the original paper. Alternatively, I may need to change the paper size as part of the zooming. Either way, I don't want to see x and y scroll bars for the div.
Another way to look at this is that I am trying to simulate an infinite page size. Any suggestions on how to implement this?

Categories