Javascript 存储window.innerWidth值,并在调整大小时计算与新值的差异?
如何存储Javascript 存储window.innerWidth值,并在调整大小时计算与新值的差异?,javascript,Javascript,如何存储window.innerWidth值,并在调整大小时计算与新值的差值 var w; function example { var onResize = function () { w = {width: window.innerWidth || document.body.clientWidth }; if (difference of old width and this (new) width is 100) { // then do some stuff } wi
window.innerWidth
值,并在调整大小时计算与新值的差值
var w;
function example {
var onResize = function () {
w = {width: window.innerWidth || document.body.clientWidth };
if (difference of old width and this (new) width is 100) {
// then do some stuff
}
window.addEventListener('resize', onResize);
onResize();
}
解决方案是将变量存储在全局变量内部或外部的onResize
,计算新旧数据之间的差异,执行某种条件:(旧宽度-新宽度)=100?
,如果差异为100,则执行一些操作
现在,从概念上讲,我知道如何实现这一点,但如何在JavaScript中真正实现它?将当前宽度存储为
oldWidth
。在resize
侦听器中,检查当前宽度是否与oldWidth
相差100px(或更多)。如果有,则执行一些操作并用当前值更新oldWidth
var oldWidth = window.innerWidth;
var onResize = function () {
var w = window.innerWidth;
if ( Math.abs( w - oldWidth ) >= 100 ) {
// then do some stuff
console.log( 'diff >= 100px' );
oldWidth = w;
}
}
window.addEventListener('resize', onResize);
首先使用一些更好的名称和一个额外的变量作为占位符。另外,我正在为显示的代码添加一个作用域,以便
w
或width
不会在该代码段之外使用
(function(){
//create a closed scope to prevent naming collision
//store the previous value for the width
var previousWidth = window.innerWidth || document.body.clientWidth;
var onResize = function () {
//calculate the current value for the width
var currentWidth = window.innerWidth || document.body.clientWidth;
//look to see if the change was more than 100
//using the absolute value here is important because it ensures
//that a change of -150 is also a difference of more than 100
if (Math.abs(previousWidth - currentWidth) > 100 ) {
// then do some stuff
//change the prior width to the current for for future references
previousWidth = currentWidth;
}
};
window.addEventListener('resize', onResize);
})()
一个完整的重构。让我们研究一种更结构化的方法,在这种方法中,我们在调整大小时累积大小,并查看历史值。这将使我们不仅可以跟踪它是否分段移动,而且还可以跟踪它通常如何移动,可以计算速度,还可以包括一些粒度
(function(){
//create an ExecutionContext to ensure there are no
//variable name collisions
//store the value of the first width of the window
var starting = getWidth();
//make this a function since it is called so often (DRY)
function getWidth(){
return window.innerWidth || document.body.clientWidth;
}
//this is a flag to determine if a resize is currently happening
var moving = false;
//this value holds the current timeout value
var tracking = null;
//this function allows for the resizing action to throttle
//at 450ms (to ensure that granular changes are tracked)
function throttle(callback){
//setTimeout returns an integer that can later be called
//with clearTimeout in order to prevent the callback from executing
tracking = setTimeout(function(){
//if this executes, it is assumed that the resize has ended
moving = false;
//checks to ensure calling the callback wont cause an error
if(toString.call(callback) == "[object Function]")callback();
},450);
}
//simple log in here but this will allow for other code to be placed
//to track the beginning of the resize
function resizeStart(){
console.log('resizing started');
}
//same as the start, this will execute on finish for extension
//purposes
function resizeEnd(){
console.log('resizing finished');
}
//this will be used to test against where the resize width value
//started at
var beginning = getWidth();
//this array will hold the widths of the page as measured during
//each resize event
var steps = [];
//seed it with the first value right now
var step = getWidth();
steps.push(step);
//these will hold the granular changes which are the differences
//between each concurrent step, only while a resize is active
var changes = [];
//the resize event handler
window.addEventListener('resize', function(){
//if a resize event is not active then call
//the start function, set the width of the beginning variable
//as an anchor so to speak, and make sure to mark resize as active
//with the moving flag
if(!moving){
resizeStart()
beginning = getWidth();
moving = true;
}else{
//if the resize event is already active (moving) then clear out
//the ending time so that it can be reconstructed since
//we are still collecting information
clearTimeout(tracking);
}
//this change will be the difference between the width now
//and the width of the last reading
var change = getWidth() - step;
//once the change is calculated we update the current width reading
//of the step
step = getWidth();
//and then store both of them (remember changes is only populated
//while resize is active)
changes.push(change);
steps.push(step);
//this sets up the timeout as noted above
throttle(function(){
//the reduce is just suming, so this takes the sum of
//the changes array
var totalChange = changes.reduce(function(a, b) {
return a + b;
});
//if the sum was positive then the resize made the window larger
var direction = totalChange > 0 ? "larger" : "smaller";
//the assumption if this callback function is executing is that
//the resize event has finished, and so the changes array
//is reset
changes = [];
//this gets back to the very original question of when
//there had been 100 pixels of change
if(Math.abs(totalChange) > 100){
console.log(Math.abs(totalChange) + " pixel granular change " + direction);
}
//this just logs what the overall change has been this whole time
console.log(Math.abs(steps[steps.length-1] - starting)+" pixel overall change");
//again noting that resize has ended, reset the "anchor" width
beginning = getWidth();
//and finally call our ending function
resizeEnd();
});
});
})()
尝试以下方法。但请注意,当用户调整窗口大小时,“调整大小”事件会定期发送。此代码将具有检测即时(最小化、最大化)或非常快发生的大小调整的效果—速度超过每渲染刻度100px。如果您想要最终调整大小的最终大小,一旦用户放开,您将需要一个超时,如以下问题的答案所示:
我不确定我看到你的障碍在哪里;实际上,你似乎对如何做到这一点有很好的想法。如果它让你克服了心理障碍,一个提示:你将使用减法,你将不得不解释一个可能的负值。(还有,我想你需要普通的括号,其中有花括号)@Katana314是的,因为减法给了我精确的差别。考虑到这一切,我似乎有点不知所措。如果我做这样的检查,如果(w-w==100),如果新旧之间的差值是100,那么做一些事情。我只是不知道这是否会起作用,或者JS是否会将其解释为旧的或新的从其自身减去,所以我基本上需要JS能够区分我的条件中的“w”哇,我甚至不接近这一点,我会检查这一点,我可能不得不问你一些事情after@Asperger你很接近,但是你需要记住,差正好为100的几率很小,这就是为什么你需要检查它是否为100或更多。而
Math.abs
用来解释正负差异(用户可以放大或缩小窗口),那么Math.Round或Math.floor呢?它对数字进行了四舍五入,那么我需要Math.abs做什么?如果我可以只是子结构?在手动调整大小的过程中仍然可以得到增量更改,使用这种方法将永远不会有大于100的差异,但是在调整大小的过程中,总的用户更改可以远远大于100@charlietfl-如果这就是我们的意图,那么简单的改变就是夹紧之前的宽度,而不是改变它。然而,这一点在最初的问题中并没有真正阐明。处理这种细微差别需要对检查100像素差异的原始声明进行修改,但这种方法仍然可以根据调整大小的细微差别进行小的修改。按照@pawel的工作方式,除非基线达到100,否则不要重置基线。我认为,要实现OP的最终目标,可能需要一个计时器。我喜欢这样written@charlietfl哦,是的,我将settimout存储在一个变量中,然后清除它。对我来说似乎是合理的。我不确定可能是资源消耗的两倍。在另一边,没有人不断地调整大小,我也会问你。如果我们只能使用“-”负运算符,为什么要使用math.abs?或者它不起作用?调整大的尺寸会产生正数。调整较小的大小将创建负数。例如,旧宽度为1000。新宽度为800。newWidth-oldWidth将为-200-200小于100,所以即使调整大小很大,我们也没有得到正确的答案。abs()将取负数并将其转换为大于100的正200。所以你会得到你想要的答案。
var previousWidth;
var detectBigChange = function () {
var newWidth = window.innerWidth || document.body.clientWidth;
if (!!previousWidth && Math.abs(newWidth - previousWidth) > 100) {
console.log("Big change!");
}
previousWidth = newWidth;
}
window.addEventListener('resize', detectBigChange);
detectBigChange();