window.devicePixelRatio
根据我使用的视网膜显示器或标准显示器返回1或2。如果我在两个显示器之间拖动窗口,此属性将发生变化。是否有办法在发生变化时触发一个监听器?
window.devicePixelRatio
根据我使用的视网膜显示器或标准显示器返回1或2。如果我在两个显示器之间拖动窗口,此属性将发生变化。是否有办法在发生变化时触发一个监听器?
您可以使用matchMedia
监听媒体查询,这将告诉您当设备像素比超过某个临界值时(不幸的是不能用于任意比例变化)。
e.g:
window.matchMedia('screen and (min-resolution: 2dppx)')
.addEventListener("change", function(e) {
if (e.matches) {
/* devicePixelRatio >= 2 */
} else {
/* devicePixelRatio < 2 */
}
});
window.matchMedia
在IE10+和所有其他现代浏览器中得到支持。min-resolution
。互联网上的大部分(或全部?)答案仅检测特定的更改。通常它们会检测值是否为2或其他值。
问题可能在于MediaQuery,因为它们只允许检查特定的硬编码值。
通过一些编程,可以动态创建媒体查询,从而检查当前值的变化。
let remove = null;
const updatePixelRatio = () => {
if(remove != null) {
remove();
}
let mqString = `(resolution: ${window.devicePixelRatio}dppx)`;
let media = matchMedia(mqString);
media.addListener(updatePixelRatio);
remove = function() {media.removeListener(updatePixelRatio)};
console.log("devicePixelRatio: " + window.devicePixelRatio);
}
updatePixelRatio();
我采用了IMO中最好的答案(由@Neil提供),并使其更加人性化,具有易读性:
function listenOnDevicePixelRatio() {
function onChange() {
console.log("devicePixelRatio changed: " + window.devicePixelRatio);
listenOnDevicePixelRatio();
}
matchMedia(
`(resolution: ${window.devicePixelRatio}dppx)`
).addEventListener("change", onChange, { once: true });
}
listenOnDevicePixelRatio();
不需要固定的边界或变量。
感谢 @florian-kirmaier 这正是我所要寻找的。如果在事件监听器中传递选项 {once: true}
,则无需手动跟踪和删除事件监听器。
(function updatePixelRatio(){
matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`)
.addEventListener('change', updatePixelRatio, {once: true});
console.log("devicePixelRatio: " + window.devicePixelRatio);
})();
我更喜欢这个选项,因为我可以提供一个回调函数,并且回调函数只在更改时触发,而不是最初触发,当不再需要时也可以停止它:
function onPixelRatioChange(cb) {
let mediaQuery
const listenerOptions = { once: true }
let firstRun = true
function onChange() {
if (firstRun) firstRun = false
else cb()
mediaQuery = matchMedia(`(resolution: ${devicePixelRatio}dppx)`)
mediaQuery.addEventListener('change', onChange, listenerOptions)
}
onChange()
return function unlisten() {
mediaQuery.removeEventListener('change', onChange, listenerOptions)
}
}
// Then use it like this:
const unlisten = onPixelRatioChange(() => {
console.log('pixel ratio changed:', devicePixelRatio)
})
// later, stop listening if desired:
unlisten()
这是@Florian答案的TypeScript对象版本
export default class DevicePixelRatioObserver {
mediaQueryList: MediaQueryList | null = null
constructor(readonly onDevicePixelRatioChanged: () => void) {
this._onChange = this._onChange.bind(this)
this.createMediaQueryList()
}
createMediaQueryList() {
this.removeMediaQueryList()
let mqString = `(resolution: ${window.devicePixelRatio}dppx)`;
this.mediaQueryList = matchMedia(mqString);
this.mediaQueryList.addEventListener('change', this._onChange)
}
removeMediaQueryList() {
this.mediaQueryList?.removeEventListener('change', this._onChange)
this.mediaQueryList = null
}
_onChange(event: MediaQueryListEvent) {
this.onDevicePixelRatioChanged()
this.createMediaQueryList()
}
destroy() {
this.removeMediaQueryList()
}
}
function watchDevicePixelRatio(callback: (ratio: number) => void, targetWindow: Window = window) {
const media = targetWindow.matchMedia(`(resolution: ${targetWindow.devicePixelRatio}dppx)`);
function handleChange() {
callback(targetWindow.devicePixelRatio);
}
media.addEventListener("change", handleChange);
return function stopWatching() {
media.removeEventListener("change", handleChange);
};
}
window.devicePixelRatio
更新时,resize
事件将会被触发。 - user2570380