问题
Update: I've created this Code Page demo to show what I'm talking about. This demo shows two methods, the first is the brute-force method and the second is Robert McKee's method.
With the first method, press the Scroll to End button to derive the vertical (y) scaling value, which is then shown next to the button that was just pushed. The list of values below the buttons, you will also see the number of 1px scrolls horizontally and vertically needed to fully scroll to the lower-left corner of the scroll-area, shown in the Scroll Y Count and Scroll X Count fields. With the scaling value now showing and the adjacent checkbox checked, pressing the Scroll to End button shows that the same number of 1px horizontal and scaled vertical scrolls now get to the lower-right end of the scroll-area.
With the second method, press the Calculate Y Scale button to calculate the y scale value without needing to actually scroll. After the value is calculated the second dive is scrolled to show that it works.
The first method finds a y scale value that allow scrolling so that the horizontal and vertical scrolls over and down such that they both get to the left side and bottom with exactly the same number of scrolls. I'm not sure why there is a difference, but the second method is very close, only one scroll different, so its good enough.
Original Question:
I need to calculate the scaling values needed to scroll the horizontal and vertical scrollbars of a div so that when the horizontal scrolling completely traverses the width of the div, the vertical scrolling also completely traverses the height of the same div.
I do this now by first manually counting the number of of calls of the $( '#div' ).scrollLeft( ++x )
jQuery function and, separately, the number of calls of the $( '#div' ).scrollTop( ++y )
function, with the x and y values starting at 0, and increasing by 1 per call, that are needed to scroll over the div's width and height, respectively. In my case the div is 540 px wide by 759 px high, and it take 342 times to cover the width and 660 for the height. From this I can calculate the y scaling value to put in the vertical scroll function call, $( '#div' ).scrollTop( ++y * yScale )
, to be 660/342 for my div. The issue is that the div's width and height aren't always the same so I can't use a pre-calculated value for the y scaling value for all possible contents that the scrolling div needs to display.
Why with a 1 pixel x and y increment isn't the number of each scroll calls not 540 and 759 rather than 342 and 660 for my specific case?
Before trying to automate the calculations, I tried calling the scrollTop function multiple times with a parameter value starting with 0, and incrementing by 1 pixel in each successive call (0, 1, 2, ... 10, 11, .., 20, etc.), and I found that the amount scrolled by each scroll call was not consistent.
I include this because with the inconsistency I found that I couldn't rely on the average scrolled amount by a few scroll calls to calculate the total number of calls needed to traverse the full distance of each div axis direction.
I can automate this with a loop that counts the number of repeated calls for each dimension, stopping counting for each direction when the respective scrollbar stops scrolling, and stopping looping when both scrollbars stop scrolling, but I'd rather not have to do this if there is a purely mathematical way to calculate the scaling values. Besides, this would look odd to the user as the div contents jumped around each time it is loaded, especially for larger contents and slow the display.
Does anyone know how to do this?
Thanks.
回答1:
If you are trying to calculate yScaling, here you go:
var elem = $('#div2a').parent()[0]; // same as divScroller[0]
var yScaling = (elem.scrollHeight-elem.clientHeight) / (elem.scrollWidth-elem.clientWidth);
which for your divs, comes out to 1.9298245614035088.
If you want the values you are trying to calculate in "Ave Scroll Y" and "Ave Scroll X", then those values are 1 and 1/1.9298245614035088 which is 0.5181818181818182.
This is why the formula works: Assume you have a viewport of 100px width, and the content inside that viewport is 400px. When fully scrolled left, the scrollLeft will be 300px (400px - 100px). 300px of the 400px will be off the screen, and the last 100px will be visible inside the viewport. That is why when you are trying to calculate the maximum value for scrollLeft, you use scrollWidth - clientWidth of the viewport (.scroller). Do the same thing to calculate the maximum scrollTop, and the Y-Scaling is the ratio between those two numbers.
回答2:
Use currentScrollX and currentScrollY for setting current position of scrollbar and destinationScrollX and destinationScrollY for where you want to go
Then each animation loop runs the following to recalculate currentScrollX and currentScrollY
var speed = 20; // adjust accordingly
// Home into destination
currentScrollX += (destinationScrollX - currentScrollX) / speed;
currentScrollY += (destinationScrollY - currentScrollY) / speed;
To end scrolling simply do something like
if (Math.abs(destinationScrollX - currentScrollX) < 0.05 && Math.abs(destinationScrollY - currentScrollY) < 0.05) {
currentScrollX = destinationScrollX;
currentScrollY = destinationScrollY;
// stop scrolling flag / code goes here
}
// At this point set scrollTop(currentScrollY) and scrollLeft(currentScrollX)
Update
If you want to scroll x and y a certain number of pixels in 30 frames based on their width / height then
var scaleX = widthOfScrollingDiv / 30;
var scaleY = heightOfScrollingDiv / 30;
You then animate for 30 frames and you'll reach the destination at the same time even if width and height aren't the same.
来源:https://stackoverflow.com/questions/60490315/how-do-you-calculate-the-number-of-times-to-call-el-scrolltop-1-to-t