想让JS弹出窗口显示在第二个(辅助)显示器上?

这是一个头疼的事情,毕竟第二个显示器技术的应用也就这几年的事。

弹出窗口的小事情

多年前,被做烂的弹窗,逼得各大浏览器纷纷出手,直接block掉多次弹窗,避免疯狂弹窗对用户的一万点暴击!

因此使用弹窗要小心,一不留神不见了!

今天忽然有人问我,“老大,能否实现弹窗到第二个显示器?” “这有啥难得,分分钟帮你搞定?”

“话说,打脸,不要太疼!”

想象一下一个会议室中的用户配备了投影仪,他们通过HDMI电缆连接到该投影仪。

我们经常不是将演示文稿镜像到远程端点,而是真正希望在投影仪上全屏显示幻灯片,而让笔记本电脑的屏幕可用于演讲者备注和幻灯片控制。这点PowerPoint做得已经非常棒了!

而网页实现这个效果,那可费劲了。

在这里插入图片描述

FireFox、IE支持

不得不说,火狐浏览器已经几乎退出市场了。这里贴上代码也仅供把玩了。

/**
 * Pop up an external window center of the page (works with dual monitor setup's)
 *
 * @constructor
 */
function PopupCenter(url, title, w, h) {
    // Fixes dual-screen position                         Most browsers      Firefox
    var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
    var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;

    var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow = window.open(url, 'scrollbars=yes,width=' + w + ',height=' + h + ',top=' + top + ',left=' + left);

    // Puts focus on the newWindow
    if (window.focus) {
        if(newWindow) {
            newWindow.focus();
        } else {
            $('<div class="has-error"><p class="help-block">Pop Up blocked. Please disable your pop up blocker to provide your bank details.</p></div>').insertBefore('.refNo');
        }
    }
    return newWindow;
}

Chrome支持

上述代码Chrome表示不支持!就这么牛逼。

“难道没办法了?”

“当然,不是!”

由国际大佬组织W3C出面,在2020年12月份出台了Presentation API规范,这个api接口允许用户自由控制投放在其他屏幕上,并和投放窗口通信。

WSC规范在此,路过不要错过

在这里插入图片描述


使用这个api,是这样子的。

  1. 首先,我们将创建一个新PresentationRequest对象,该对象将包含我们要在辅助附加显示器上显示的URL。
const presentationRequest = new PresentationRequest('receiver.html');
  1. 做个控制事件及监听事件:
const presentationRequest = new PresentationRequest(['receiver/index.html']);

// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
let presentationConnection;

function onPresentButtonClick() {
  presentationRequest.start()
  .then(connection => {
    console.log('Connected to ' + connection.url + ',id: ' + connection.id);
  })
  .catch(error => {
    console.log(error);
  });
}

//监视连接是否可用
presentationRequest.addEventListener('connectionavailable', function(event) {
  presentationConnection = event.connection;
  presentationConnection.addEventListener('close', function() {
    log('> Connection closed.');
  });
  presentationConnection.addEventListener('terminate', function() {
    log('> Connection terminated.');
  });
  presentationConnection.addEventListener('message', function(event) {
    log('> ' + event.data);
  });
});

//发送消息
function() {
  const message = document.querySelector('#message').value.trim();
  const lang = document.body.lang || 'en-US';

  log('Sending "' + message + '"...');
  presentationConnection.send(JSON.stringify({message, lang}));
}

//关闭连接,关闭连接后无法再控制弹出窗口
function() {
  log('Closing connection...');
  presentationConnection.close();
}
//关闭连接后,换可以重新再次连接,这里需要指定id
presentationRequest.reconnect(presentationId);

//关闭弹窗,结束连接调用
function() {
  log('Terminating connection...');
  presentationConnection.terminate();
}


//监视可用的显示器
presentationRequest.getAvailability()
.then(availability => {
  console.log('Available presentation displays: ' + availability.value);
  availability.addEventListener('change', function() {
    console.log('> Available presentation displays: ' + availability.value);
  });
})
.catch(error => {
  console.log('Presentation availability not supported,' + error.name + ': ' +
      error.message);
});
  1. 弹窗端可响应连接消息
let connectionIdx = 0;
let messageIdx = 0;

//如果有连接建立,则调用该函数
function addConnection(connection) {
  connection.connectionId = ++connectionIdx;
  addMessage('New connection #' + connectionIdx);

  connection.addEventListener('message', function(event) {
    messageIdx++;
    const data = JSON.parse(event.data);
    const logString = 'Message ' + messageIdx + ' from connection #' +
        connection.connectionId + ': ' + data.message;
    addMessage(logString, data.lang);
    maybeSetFruit(data.message);
    connection.send('Received message ' + messageIdx);
  });

  connection.addEventListener('close', function(event) {
    addMessage('Connection #' + connection.connectionId + ' closed,reason = ' +
        event.reason + ',message = ' + event.message);
  });
};

/* Utils */

const fruitEmoji = {
  'grapes':      '\u{1F347}',
  'watermelon':  '\u{1F349}',
  'melon':       '\u{1F348}',
  'tangerine':   '\u{1F34A}',
  'lemon':       '\u{1F34B}',
  'banana':      '\u{1F34C}',
  'pineapple':   '\u{1F34D}',
  'green apple': '\u{1F35F}',
  'apple':       '\u{1F34E}',
  'pear':        '\u{1F350}',
  'peach':       '\u{1F351}',
  'cherries':    '\u{1F352}',
  'strawberry':  '\u{1F353}'
};

function addMessage(content, language) {
  const listItem = document.createElement("li");
  if (language) {
    listItem.lang = language;
  }
  listItem.textContent = content;
  document.querySelector("#message-list").appendChild(listItem);
};

function maybeSetFruit(message) {
  const fruit = message.toLowerCase();
  if (fruit in fruitEmoji) {
    document.querySelector('#main').textContent = fruitEmoji[fruit];
  }
};

//文档载入后,监听连接
document.addEventListener('DOMContentLoaded', function() {
  if (navigator.presentation.receiver) {
    navigator.presentation.receiver.connectionList.then(list => {
      list.connections.map(connection => addConnection(connection));
      list.addEventListener('connectionavailable', function(event) {
        addConnection(event.connection);
      });
    });
  }
});
  1. 显示效果
    在点击按钮后,会弹出窗口询问,需要弹出窗口投影到哪个设备。

在这里插入图片描述


比如下面的效果,就更炫了。

在这里插入图片描述


5. 另外,Chrome浏览器已经增加了“投射…”菜单项,功能类似。

在网页内点击右键会出来选项,老实说,我没测试成功。

另外,如果需要调试接收端,可转到 chrome://inspect页面,选择其他,然后点击当前显示的URL旁边的“检查”链接。

在这里插入图片描述


最后说明下,最低版本是Chrome 66,并且支持Chrome OS,Linux和Windows平台。Mac支持将在以后提供。

最后,奉上演示页面:点击此处

小结

感觉Chrome一统江山后,后遗症也慢慢出现了,每次升级,好像都没啥让人眼前一亮的功能了。

你是否也有同感,留下你的评论。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)