JavaScript에서 브라우저의 "확대"이벤트 캐치


162

사용자가 페이지에서 확대 / 축소를 변경할 때 JavaScript를 사용하여 감지 할 수 있습니까? 단순히 "zoom"이벤트를 잡고 이에 응답하고 싶습니다 (window.onresize 이벤트와 유사).

감사.


13
최신 브라우저는 페이지가 확대 될 때 onresize 이벤트를 시작한다고 생각합니다.
epascarello 2016 년

1
비슷한 문제가 있지만 확대 / 축소가 변경되는시기를 알고 싶지 않고 페이지가로드 될 때 확대 / 축소 값도 알고 싶습니다.
Nosredna

3
정말 중복되지 않습니다. 여기서 질문은 확대 / 축소 수준을 결정하지 않고 이벤트를 잡는 것에 관한 것입니다.
Assaf Lavie

5
@epascarello - 예,하지만 내 댓글을 무효화하지 않습니다
HorusKol

7
최신 브라우저에서 발생하는 'onresize'에 대해 확인하고 싶습니다. 지금까지 확대 또는 축소 할 때 newset Chrome (33), FF (28), IE (9 번째 모드의 11 및 11)가 모두 올바르게 이벤트를 트리거하는 것을 봅니다.
Brock

답변:


77

확대 / 축소가 있는지 능동적으로 감지 할 수있는 방법이 없습니다. 나는 당신이 그것을 구현하려고 시도하는 방법에 대한 좋은 항목을 발견했습니다.

줌 레벨을 감지하는 두 가지 방법을 찾았습니다. 확대 / 축소 수준 변경을 감지하는 한 가지 방법은 백분율 값이 확대되지 않는다는 사실에 의존합니다. 백분율 값은 뷰포트 너비를 기준으로하므로 페이지 확대 / 축소의 영향을받지 않습니다. 하나의 위치에 백분율이 있고 다른 하나의 위치가 픽셀에있는 두 개의 요소를 삽입하면 페이지가 확대 / 축소 될 때 분리됩니다. 두 요소의 위치 사이의 비율을 찾으면 확대 / 축소 수준이 있습니다. 테스트 사례를 참조하십시오. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3

위 게시물의 도구를 사용하여 수행 할 수도 있습니다. 문제는 페이지 확대 / 축소 여부에 대한 교육 된 추측을하는 것입니다. 이것은 다른 브라우저보다 일부 브라우저에서 더 잘 작동합니다.

확대 / 축소 중에 페이지를로드하면 페이지가 확대되었는지 확인할 수있는 방법이 없습니다.


1
바디의 onload 핸들러 내에서 크기 매개 변수를 확인할 수 있습니다. 흥미롭게도 IE8 대 9를 디버깅 할 때 본문의 크기 조정 핸들러는 IE8의 문서를 전달하는 반면 IE9는 Chrome과 마찬가지로 창을 전달합니다.
Walter K

두 요소를 정확히 동일한 위치에 배치하고 확대 / 축소 상태에서 페이지를로드하면 두 요소 사이에 변위가 없습니까? 페이지가 이미 확대되었는지 여부를 알 수 없습니까?
vijayant 2016 년

또한document.body.offsetWidth
Samy Bencherif

이와 같은 방법을 사용하면 사용자가 창 크기를 조정할 때도 발생하므로 크기 조정 이벤트 리스너를 사용하지 않는 이유는 무엇입니까? 이 경우에도 실행 가능한 솔루션입니다.
hewiefreeman

12

이 JavaScript를 사용하여 Zoom "이벤트"에 반응합니다.
창 너비를 폴링합니다. (이 페이지에서 다소 제안했듯이 (Ian Elliott가 링크 한) : http://novemberborn.net/javascript/page-zoom-ff3 [archive] )

IE가 아닌 Chrome, Firefox 3.6 및 Opera에서 테스트되었습니다.

감사합니다, 매그너스

var zoomListeners = [];

(function(){
  // Poll the pixel width of the window; invoke zoom listeners
  // if the width has been changed.
  var lastWidth = 0;
  function pollZoomFireEvent() {
    var widthNow = jQuery(window).width();
    if (lastWidth == widthNow) return;
    lastWidth = widthNow;
    // Length changed, user must have zoomed, invoke listeners.
    for (i = zoomListeners.length - 1; i >= 0; --i) {
      zoomListeners[i]();
    }
  }
  setInterval(pollZoomFireEvent, 100);
})();

8
창 크기를 조정하면 잘못된 긍정은 어떻습니까?
gcb

5
그러나 onresize 핸들러를 구현할 때 이러한 경우를 필터링 할 수 있습니다. 솔루션의 기본 사항은 여기에 있습니다.
Stijn de Witt

@StijndeWitt 이것을 읽은 후 제안 된 경로를 이해하기 시작했습니다. 이제 크기 조정 이벤트, 특히 모바일에서 필터링하는 솔루션을 개발 중입니다. 누군가?
lowtechsun

어쩌면 간격 값을 사용하여 크기를 조정하고 확대 / 축소 할 수 있습니까? 확대 / 축소는 창 너비를> x 픽셀만큼 즉시 변경합니다.
Sebastien

1
거짓 긍정이 문제입니다. 종횡비가 유지되는지 확인하여 모든 오 탐지의 99.99 %를 제거하지 않습니까? 스크립트가 마지막 비율을 기억하고 새 비율을 계산하고 동일한 지 확인하십시오. 너비가 다른 것과 결합하면 좋은 기초를 가져야합니다
Biepbot Von Stirling

11

좋은 소식 여러분어떤 사람들은! 최신 브라우저는 확대 / 축소가 변경 될 때 창 크기 조정 이벤트를 트리거합니다.


Android 용 Chrome 및 Firefox는 확대시 크기 조정 이벤트를 트리거하지 않습니다.
lowtechsun

5
확대 / 축소로 크기 조정 이벤트를 트리거하지 않으려는 경우에는 좋은 소식이 아닙니다.
Reahreic 2012

12
더 좋은 소식은 크기 조정 이벤트와는 별개의 실제 확대 / 축소 이벤트입니다.
Vincent

3
둘 다 사실입니다. 편집했습니다.
Ben

어떻게 든 줌을 설정할 수 있습니까?
oldboy

9

다음과 같이 px_ratio를 정의하십시오.

px ratio = 물리적 픽셀 대 CSS px의 비율

하나의 확대 / 축소 페이지가 있으면 뷰포트 pxes (px는 픽셀과 다름)가 줄어들고 화면에 맞아야합니다. 따라서 화면 비율 (물리적 픽셀 / CSS_px)이 커져야합니다.

그러나 창 크기 조정에서 화면 크기와 픽셀 수가 줄어 듭니다. 비율이 유지됩니다.

확대 / 축소 : windows.resize 이벤트 트리거-> px_ratio 변경

그러나

크기 조정 : windows.resize 이벤트 트리거-> px_ratio를 변경하지 않습니다

//for zoom detection
px_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;

$(window).resize(function(){isZooming();});

function isZooming(){
    var newPx_ratio = window.devicePixelRatio || window.screen.availWidth / document.documentElement.clientWidth;
    if(newPx_ratio != px_ratio){
        px_ratio = newPx_ratio;
        console.log("zooming");
        return true;
    }else{
        console.log("just resizing");
        return false;
    }
}

핵심은 CSS PX와 Physical Pixel의 차이점입니다.

https://gist.github.com/abilogos/66aba96bb0fb27ab3ed4a13245817d1e


허용되는 답변 IMO 여야합니다. 지금까지 완벽하게 작동합니다, 감사합니다! 관심있는 사람이 있다면 gist.github.com/souporserious/b44ea5d04c38c2e7ff32cd1912a17cd0에 맞춤 이벤트로 묶으십시오 .
Soorserious

6

이것은 나를 위해 작동합니다 :

        var deviceXDPI = screen.deviceXDPI;
        setInterval(function(){
            if(screen.deviceXDPI != deviceXDPI){
                deviceXDPI = screen.deviceXDPI;
                ... there was a resize ...
            }
        }, 500);

IE8에서만 필요합니다. 다른 모든 브라우저는 자연스럽게 크기 조정 이벤트를 생성합니다.


3

yonran감지 할 수 있는 멋진 플러그인 이 있습니다. 다음은 StackOverflow 대해 이전에 답변 한 질문입니다. 대부분의 브라우저에서 작동합니다. 응용 프로그램은 다음과 같이 간단합니다.

window.onresize = function onresize() {
  var r = DetectZoom.ratios();
  zoomLevel.innerHTML =
    "Zoom level: " + r.zoom +
    (r.zoom !== r.devicePxPerCssPx
        ? "; device to CSS pixel ratio: " + r.devicePxPerCssPx
        : "");
}

데모


Android 4.4.2 용 Firefox에서는 작동하지 않습니다. 또한 모바일의 FF Always enable zoom에서는 접근성 옵션 의 버튼을 선택하십시오. 데모는 변화에 반응하지 않습니다.
lowtechsun

2

창 너비 변경을 추적하여 이전 솔루션의 개선을 제안하고 싶습니다. 고유 한 이벤트 리스너 배열을 유지하는 대신 기존 Javascript 이벤트 시스템을 사용하고 너비가 변경 될 때 고유 한 이벤트를 트리거하고 이벤트 핸들러를 바인딩 할 수 있습니다.

$(window).bind('myZoomEvent', function() { ... });

function pollZoomFireEvent() 
{ 

    if ( ... width changed ... ) {
        $(window).trigger('myZoomEvent');
    }
}

스로틀 / 디 바운스 는 처리기의 호출 속도를 줄이는 데 도움이 될 수 있습니다.


1
스로틀 / 디 바운스는 다른 이벤트 (예 : 마우스 이동 또는 키업)에 의해 폴링이 트리거 된 경우에만 유용합니다.
fuzzyTew

1

최소한 깨지지 않는 공간을 포함하는 div를 삽입하고 (숨겨져 있음) 정기적으로 높이를 확인하여 텍스트 크기 조정 이벤트와 확대 / 축소 비율을 얻을 수 있습니다. 높이가 변경되면 텍스트 크기가 변경되었습니다. 창이 전체 페이지 모드로 확대 되어도 높이가 동일한 경우에도 확대 / 축소 비율이 표시됩니다. 높이 비율).


1
<script>
var zoomv = function() {
  if(topRightqs.style.width=='200px){
  alert ("zoom");
  }
};
zoomv();
</script>

1

iOS 10에서는 이벤트에 이벤트 리스너를 추가 touchmove하고 현재 이벤트로 페이지가 확대되어 있는지 감지 할 수 있습니다.

var prevZoomFactorX;
var prevZoomFactorY;
element.addEventListener("touchmove", (ev) => {
  let zoomFactorX = document.documentElement.clientWidth / window.innerWidth;
  let zoomFactorY = document.documentElement.clientHeight / window.innerHeight;
  let pageHasZoom = !(zoomFactorX === 1 && zoomFactorY === 1);

  if(pageHasZoom) {
    // page is zoomed
    
    if(zoomFactorX !== prevZoomFactorX || zoomFactorY !== prevZoomFactorY) {
      // page is zoomed with this event
    }
  }
  prevZoomFactorX = zoomFactorX;
  prevZoomFactorY = zoomFactorY;
});


1

이것은 9 살짜리 질문이지만 문제는 지속됩니다!

프로젝트에서 확대 / 축소를 제외하는 동안 크기 조정을 감지 했으므로 크기를 조정하고 확대 / 축소를 독점적으로 감지하도록 코드를 편집했습니다. 대부분 의 시간에 작동 하므로 대부분 프로젝트에 충분하면 도움이 될 것입니다! 내가 지금까지 테스트 한 시간의 100 % 확대를 감지합니다. 유일한 문제는 사용자가 미치거나 (예 : 창 크기를 조정) 창 지연이 발생하면 창 크기 조정 대신 확대 / 축소로 실행될 수 있다는 것입니다.

그것은 변화를 감지하여 작동 window.outerWidth또는 window.outerHeightA의 변화를 감지하면서 크기를 조절 창으로 window.innerWidth또는 window.innerHeight줌으로 크기 조절 창에서 독립을.

//init object to store window properties
var windowSize = {
  w: window.outerWidth,
  h: window.outerHeight,
  iw: window.innerWidth,
  ih: window.innerHeight
};

window.addEventListener("resize", function() {
  //if window resizes
  if (window.outerWidth !== windowSize.w || window.outerHeight !== windowSize.h) {
    windowSize.w = window.outerWidth; // update object with current window properties
    windowSize.h = window.outerHeight;
    windowSize.iw = window.innerWidth;
    windowSize.ih = window.innerHeight;
    console.log("you're resizing"); //output
  }
  //if the window doesn't resize but the content inside does by + or - 5%
  else if (window.innerWidth + window.innerWidth * .05 < windowSize.iw ||
    window.innerWidth - window.innerWidth * .05 > windowSize.iw) {
    console.log("you're zooming")
    windowSize.iw = window.innerWidth;
  }
}, false);

참고 : 내 솔루션은 KajMagnus와 비슷하지만 나에게 더 효과적이었습니다.


2
나는 당신에게 맞는 해결책이 있다는 것을 알 수 있기 때문에 투표하지 않고 코드가 무엇을하는지 이해하지만 0.05적어도 좋은 설명을 제공하지 않는 등의 마법 번호를 사용하지 않는 것이 좋습니다 . ;-) 예를 들어 Chrome에서는 특히 10 %가 브라우저가 확대 할 수있는 최소 크기이지만 다른 브라우저에서는 이것이 사실인지 확실하지 않습니다. 참고로, 항상 코드가 테스트되었는지 확인하고 방어하거나 개선 할 수 있도록 준비하십시오.
Nolo

흥미로운 접근
oldboy

1

깨끗한 해결책은 다음과 같습니다.

// polyfill window.devicePixelRatio for IE
if(!window.devicePixelRatio){
  Object.defineProperty(window,'devicePixelRatio',{
    enumerable: true,
    configurable: true,
    get:function(){
      return screen.deviceXDPI/screen.logicalXDPI;
    }
  });
}
var oldValue=window.devicePixelRatio;
window.addEventListener('resize',function(e){
  var newValue=window.devicePixelRatio;
  if(newValue!==oldValue){
    // TODO polyfill CustomEvent for IE
    var event=new CustomEvent('devicepixelratiochange');
    event.oldValue=oldValue;
    event.newValue=newValue;
    oldValue=newValue;
    window.dispatchEvent(event);
  }
});

window.addEventListener('devicepixelratiochange',function(e){
  console.log('devicePixelRatio changed from '+e.oldValue+' to '+e.newValue);
});


이것은 꽤 좋은 솔루션처럼 보이며 프록시를 사용하면 인터셉터로 과부 속성을 클로버 할 필요조차 없습니다 .DPR을 업데이트하는 것이 모든 브라우저가 사용자가 확대 / 축소했을 때 수행해야 할 작업인지 확인합니까? .. 그 아이디어를 긁으십시오-창을 프록시 할 수 없습니다, 아마도 "matchMedia"를 사용하는 해결책이있을 수 있지만 사실 / 거짓 일뿐이므로 같은 아날로그 값 변경을 테스트하는 방법을 잘 모르겠습니다. DPR ...
Jon z

0

resize 이벤트 는 이벤트를 on에 첨부 window한 다음 body( .getBoundingClientRect () ) 와 같은 다른 요소 의 값을 읽어 최신 브라우저에서 작동합니다 .

일부 이전 브라우저에서는 모든 HTML 요소에 크기 조정 이벤트 핸들러를 등록 할 수있었습니다. onresize 속성을 설정하거나 addEventListener ()를 사용하여 요소에 핸들러를 설정할 수 있습니다. 그러나 크기 조정 이벤트는 윈도우 객체에서만 발생합니다 (즉, document.defaultView에 의해 반환 됨). window 객체에 등록 된 핸들러 만 크기 조정 이벤트를 수신합니다 .

window.addEventListener("resize", getSizes, false)
        
function getSizes(){
  let body = document.body
  console.log(body.clientWidth +"px x "+ body.clientHeight + "px")
}

다른 대안 : ResizeObserver API

레이아웃에 따라 특정 요소의 크기 조정을 볼 수 있습니다.

확대 / 축소 할 때 컨테이너 상자의 크기가 조정되므로«반응 형»레이아웃에서 잘 작동합니다.

function watchBoxchange(e){
 // console.log(e[0].contentBoxSize.inlineSize+" "+e[0].contentBoxSize.blockSize)
 info.textContent = e[0].contentBoxSize.inlineSize+" * "+e[0].contentBoxSize.blockSize + "px"
}

new ResizeObserver(watchBoxchange).observe(fluid)
#fluid {
  width: 200px;
  height:100px;
  overflow: auto;
  resize: both;
  border: 3px black solid;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 8vh
}
<div id="fluid">
   <info id="info"></info> 
</div>


사용자 제스처 이벤트에서 자바 스크립트 작업을 오버로드하지 않도록주의하십시오 . 다시 그리기가 필요할 때마다 requestAnimationFrame을 사용하십시오 .


0

MDN에 따르면 "matchMedia"는이를 수행하는 올바른 방법입니다 https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio#Monitoring_screen_resolution_or_zoom_level_changes

각 인스턴스는 한 번에 하나의 MQ를 볼 수 있기 때문에 관심있는 그렇다면 그것은 조금 까다로운의 모든 당신이 매처 (matcher)의 무리를 할 필요 줌 레벨 변경 ..하지만 브라우저가 이벤트를 발광을 담당하고 있기 때문에 그것은 아마 여전히 폴링보다 성능이 뛰어나며 콜백을 조절하거나 디 바운싱하거나 애니메이션 프레임이나 그 밖의 것에 고정시킬 수 있습니다. 여기서 매우 딱딱한 구현이 있습니다.

코드 스 니펫을 실행하고 브라우저에서 확대 및 축소하고 마크 업의 업데이트 된 값을 확인하십시오. Firefox에서만 테스트했습니다! lemme는 문제가 있는지 알고 있습니다.

const el = document.querySelector('#dppx')

if ('matchMedia' in window) {
  function observeZoom(cb, opts) {
    opts = {
      // first pass for defaults - range and granularity to capture all the zoom levels in desktop firefox
      ceiling: 3,
      floor: 0.3,
      granularity: 0.05,
      ...opts
    }
    const precision = `${opts.granularity}`.split('.')[1].length

    let val = opts.floor
    const vals = []
    while (val <= opts.ceiling) {
      vals.push(val)
      val = parseFloat((val + opts.granularity).toFixed(precision))
    }

    // construct a number of mediamatchers and assign CB to all of them
    const mqls = vals.map(v => matchMedia(`(min-resolution: ${v}dppx)`))

    // poor person's throttle
    const throttle = 3
    let last = performance.now()
    mqls.forEach(mql => mql.addListener(function() {
      console.debug(this, arguments)
      const now = performance.now()
      if (now - last > throttle) {
        cb()
        last = now
      }
    }))
  }

  observeZoom(function() {
    el.innerText = window.devicePixelRatio
  })
} else {
  el.innerText = 'unable to observe zoom level changes, matchMedia is not supported'
}
<div id='dppx'>--</div>


-4

3 살짜리 링크에 답장을했지만 여기에 더 적합한 답변이 있다고 생각합니다.

다음과 같이 .css 파일을 만듭니다.

@media screen and (max-width: 1000px) 
{
       // things you want to trigger when the screen is zoomed
}

EG :-

@media screen and (max-width: 1000px) 
{
    .classname
    {
          font-size:10px;
    }
}

위의 코드는 화면이 약 125 %로 확대 될 때 글꼴 '10px'의 크기를 만듭니다. '1000px'의 값을 변경하여 다른 줌 레벨을 확인할 수 있습니다.


max-width확대 / 축소 비율과 의 관계는 무엇입니까 ?
seebiscuit

이 코드는 각 <1000px 화면에서 실행되며 확대 / 축소와 아무 관련이 없습니다
Artur Stary

@ArturStary 브라우저가 확대되었는지 감지하는 방법은 없지만 많은 해결 방법이 있으며 그중 하나가 내 대답에서 언급 한 것입니다. 또한, 나는 당신이 다른 줌 레벨의 효과를 줄 것이다 다양한 화면 크기를 확인하기 위해 1000px의 값을 변경할 수 있다고했다
Saumil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.