浏览器跨标签星球火了,简单探究一下实现原理
点击关注公众号,”技术干货”及时达!output3.gif一、前言最近 推特上 一位懂设计和写代码的大神一个两个浏览器之间 星球粒子交互的动画火了, 让人看了大呼脑洞大开, 浏览器竟然还能这么玩!!!
准备自己也搞搞玩一下
output3.gif二、实现原作者的粒子动画非常炫酷, 但是不是我们本文重点, 我们通过一个元素在不同窗口的拖拽实现一个可以变幻的例子来学习一下原理, 后续在实现一个稍微复杂的多窗口的小游戏。关于粒子动画的内容,有兴趣的小伙伴可以自己实现
其实实现类似的功能需要的难点并不多,不在乎以下几个步骤
1、 屏幕坐标和窗口坐标转换2、 跨标签通讯1、 先来看第一个点, 获取屏幕坐标与窗口坐标//屏幕坐标转换为窗口坐标
constscreenToClient=(screenX,screenY)={
constclienX=screenX-window.screenX;
constclienY=screenY-window.screenY-barHeight();
return[clienX,clienY];
};
//窗口坐标转换为屏幕坐标
constclientToScreen=(clienX,clienY)={
constscreenX=clienX+window.screenX;
constscreenY=clienY+window.screenY+barHeight();
return[screenX,screenY];
};
我们先简单实现一个卡片, 通过url上面传递颜色值, 设置定位
在卡片本上设置上点击拖动等事件
!DOCTYPEhtml
htmllang="en"
head
metacharset="UTF-8"/
metaname="viewport"content="width=device-width,initial-scale=1.0"/
title跨标签通讯/title
/head
style
.card{
width:300px;
height:300px;
background-color:#f00;
position:fixed;
top:100px;
left:100px;
}
/style
body
跨标签通讯
divclass="card"card/div
/body
script
constbarHeight=()=window.outerHeight-window.innerHeight;
constcardDom=document.querySelector(".card");
cardDom.style.top=100+"px";
cardDom.style.left=100+"px";
cardDom.style.background=
newURLSearchParams(window.location.search).get("color")||"red";
window.onload=function(){
cardDom.onmousedown=function(e){
cardDom.style.cursor="pointer";
letx=e.pageX-cardDom.offsetLeft;
lety=e.pageY-cardDom.offsetTop;
window.onmousemove=function(e){
cardDom.style.left=e.clientX-x+"px";
cardDom.style.top=e.clientY-y+"px";
//发送消息
constclientCoordinateX=e.clientX-
constclientCoordinateY=e.clientY-
constScreenCoordinate=clientToScreen(
clientCoordinateX,
clientCoordinateY
sendMessage(ScreenCoordinate);
window.onmouseup=function(){
window.onmousemove=null;
window.onmouseup=null;
cardDom.style.cursor="unset";
/script
/html
2、 跨标签传输单个元素的拖动就实现了, 很简单, 如何让其他标签的元素也能同步进行, 需要实现跨标签方案了, 可以参考该文章- 跨标签页通信的8种方式
我们就选择第一种,使用 BroadCast Channel, 使用也很简单
//创建BroadcastChannel
constchannel=newBroadcastChannel("myChannel");
//监听消息
channel.onmessage=(event)={
//处理接收到的消息
console.log('接收',event)
};
//发送消息
constsendMessage=(message)={
channel.postMessage(message);
};
只需要在移动时发送消息, 再其他标签页就可以接收到值了, 现在关键的就是收到发送的坐标点后, 如何处理, 其实关键就是要让几个窗口的卡片位置转化到同一个纬度, 让其再超出浏览器的时候,再另一个窗口的同一个位置出现, 所以就需要将窗口坐标转化成屏幕坐标,发送给其他窗口后, 再转化成窗口坐标进行渲染即可
//鼠标移动发送消息的时候,窗口坐标转化成屏幕坐标
window.onmousemove=function(e){
cardDom.style.left=e.clientX-x+"px";
cardDom.style.top=e.clientY-y+"px";
constclientCoordinateX=e.clientX-
constclientCoordinateY=e.clientY-
constScreenCoordinate=clientToScreen(
clientCoordinateX,
clientCoordinateY
sendMessage(ScreenCoordinate);
//接收消息的时候,屏幕坐标转化成窗口坐标
channel.onmessage=(event)={
//处理接收到的消息
const[clienX,clienY]=screenToClient(...event.data);
//不同窗口的卡片要在同一个位置,要放到同一个坐标系下面,保持屏幕坐标一致
cardDom.style.left=clienX+"px";
cardDom.style.top=clienY+"px";
};
完整代码实现如下
!DOCTYPEhtml
htmllang="en"
head
metacharset="UTF-8"/
metaname="viewport"content="width=device-width,initial-scale=1.0"/
title跨标签通讯/title
/head
style
.card{
width:300px;
height:300px;
background-color:#f00;
position:fixed;
top:100px;
left:100px;
}
/style
body
跨标签通讯
divclass="card"card/div
/body
script
constbarHeight=()=window.outerHeight-window.innerHeight;
constcardDom=document.querySelector(".card");
cardDom.style.top=100+"px";
cardDom.style.left=100+"px";
cardDom.style.background=
newURLSearchParams(window.location.search).get("color")||"red";
//屏幕坐标转换为窗口坐标
constscreenToClient=(screenX,screenY)={
constclienX=screenX-window.screenX;
constclienY=screenY-window.screenY-barHeight();
return[clienX,clienY];
//窗口坐标转换为屏幕坐标
constclientToScreen=(clienX,clienY)={
constscreenX=clienX+window.screenX;
constscreenY=clienY+window.screenY+barHeight();
return[screenX,screenY];
//创建BroadcastChannel
constchannel=newBroadcastChannel("myChannel");
//监听消息
channel.onmessage=(event)={
//处理接收到的消息
const[clienX,clienY]=screenToClient(...event.data);
//不同窗口的卡片要在同一个位置,要放到同一个坐标系下面,保持屏幕坐标一致
cardDom.style.left=clienX+"px";
cardDom.style.top=clienY+"px";
//发送消息
constsendMessage=(message)={
channel.postMessage(message);
window.onload=function(){
cardDom.onmousedown=function(e){
cardDom.style.cursor="pointer";
letx=e.pageX-cardDom.offsetLeft;
lety=e.pageY-cardDom.offsetTop;
window.onmousemove=function(e){
cardDom.style.left=e.clientX-x+"px";
cardDom.style.top=e.clientY-y+"px";
//发送消息
constclientCoordinateX=e.clientX-
constclientCoordinateY=e.clientY-
constScreenCoordinate=clientToScreen(
clientCoordinateX,
clientCoordinateY
sendMessage(ScreenCoordinate);
window.onmouseup=function(){
window.onmousemove=null;
window.onmouseup=null;
cardDom.style.cursor="unset";
/script
/html
三、总结本文通过移动一个简单的图形, 在不同浏览器之间穿梭变换, 初步体验了多个浏览器之间如何进行交互, 通过拖拽元素,通过跨标签的通讯, 将当前窗口元素的位置进行发送, 另一个窗口进行实时接收, 然后通过屏幕坐标和窗口坐标进行转换, 就能实现,从一个浏览器拖动到另一个浏览器时, 变化元素颜色的功能了, 当然变化背景色只是举例子, 你也可以变化扑克牌, 变化照片, 这样看起来像变魔术一样,非常神奇,看似浏览器不同标签之间没有联系,当以这种方式产生联系后, 就会产生很多不可思议的神奇事情。就像国外大神的多标签页的两个星球粒子, 产生吸引 融合的效果。原理其实是一样的。
四、加餐在通过小demo的学习,知道多浏览器的玩法后, 我们在实现一个更有意思的小游戏,通过浏览器化身一个小木棒, 接小球游戏, 先看一下 gif
output3.gif点击查看文章多标签通讯--实现用浏览器接小球游戏
点击关注公众号,”技术干货”及时达!
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线