前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >轻松掌握屏幕坐标和窗口通信的实用技巧

轻松掌握屏幕坐标和窗口通信的实用技巧

作者头像
友儿
发布2024-09-07 13:20:54
980
发布2024-09-07 13:20:54
举报
文章被收录于专栏:友儿

我们通过一个实战例子来学习屏幕坐标、窗口通信

效果图

思考一个问题,上述效果图是不是多个窗口公用一个元素?

  • 显然这是不可能的,肯定是三个元素。
  • 同一个页面通过url传参的方式根据参数不同,给元素设置不同的背景。

做到上述效果图需要哪些必要条件?

  • 保证元素的位置在同一个坐标系下相同。
  • 只有在电脑屏幕下,它们的坐标系才是相同的。

涉及到的知识点

导航栏的高度计算

代码语言:javascript
复制
   //获取浏览器窗口的工具栏、菜单栏和边框等元素的总高度
   function barHeight() {
       return window.outerHeight - window.innerHeight;
   }

屏幕坐标和视口坐标的转换 解析图

代码语言:javascript
复制
   //将视口坐标转换为屏幕坐标
   function clientToScreen(clientX, clientY) {
       //clientX, clientY 是视口坐标
       //window.screenX 、window.screenY 是浏览器窗口左上角相对于屏幕左上角的距离
       let screenX = clientX + window.screenX;
       //注意:window.screenY 是浏览器窗口左上角相对于屏幕左上角的距离,不包括浏览器窗口的工具栏、菜单栏和边框等元素的总高度
       let screenY = clientY + window.screenY + barHeight();
       return [screenX, screenY];
   }
   //将屏幕坐标转换为视口坐标
   function screenToClient(screenX, screenY) {
       let clientX = screenX - window.screenX;
       let clientY = screenY - window.screenY - barHeight();
       return [clientX, clientY];
   }

拖拽事件

代码语言:javascript
复制
  // 选择类名为.container 的元素
  const card = document.querySelector('.container');
  // 为选中的元素添加鼠标按下事件监听器
  card.onmousedown = function (e) {
  // 计算鼠标指针在卡片元素上的相对偏移量
  const x = e.pageX - card.offsetLeft;
  const y = e.pageY - card.offsetTop;

  window.onmousemove = function (e) {
      // 根据相对偏移量和鼠标移动事件的坐标计算卡片新的位置
      let cx = e.pageX - x;
      let cy = e.pageY - y;
      // 设置卡片元素的新位置
      card.style.left = cx + "px";
      card.style.top = cy + "px";
  }
  window.onmouseup = function () {
      // 释放鼠标时,取消鼠标移动和鼠标释放的事件监听器
      window.onmousemove = null;
      window.onmouseup = null;
  }
  }

窗口之间的通信

代码语言:javascript
复制
  // 创建一个名为'card'的广播频道,这个频道允许不同窗口或标签之间的脚本进行通信
  const channel = new BroadcastChannel('card');
  // 将当前窗口元素位置的坐标转换为屏幕坐标
  let points = clientToScreen(cx, cy);
  // 向其他窗口传递当前窗口元素位置的屏幕坐标
  channel.postMessage(points);

  // 监听其他窗口传递过来的消息
  channel.onmessage = function (event) {
  // 使用展开运算符将事件数据转换为当前可视坐标
  let [clientX, clientY] = screenToClient(...event.data);
  // 设置元素的left属性值,将视口的X坐标应用于card元素
  card.style.left = clientX + "px"; 
  // 设置元素的top属性值,将视口的Y坐标应用于card元素
  card.style.top = clientY + "px"; 

完整代码

  • html
代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>屏幕坐标和窗口通信</title>
    <link rel="stylesheet" href="static/css/reset.css">
    <link rel="stylesheet" href="static/css/index.css">
</head>
<body>
    <div class="container"></div>
    <script src="static/js/index.js"></script>
</body>
</html>
  • css
代码语言:javascript
复制
.container{
    width:300px;
    height: 300px;
    position: absolute;
}
  • js
代码语言:javascript
复制

//获取浏览器窗口的工具栏、菜单栏和边框等元素的总高度
function barHeight() {
    return window.outerHeight - window.innerHeight;
}

//将视口坐标转换为屏幕坐标
function clientToScreen(clientX, clientY) {
   let screenX = clientX + window.screenX;
   let screenY = clientY + window.screenY + barHeight();
   return [screenX, screenY];
}
//将屏幕坐标转换为视口坐标
function screenToClient(screenX, screenY) {
   let clientX = screenX - window.screenX;
   let clientY = screenY - window.screenY - barHeight();
   return [clientX, clientY];
}

//创建一个名为'card'的广播频道,这个频道允许不同窗口或标签之间的脚本进行通信
const channel = new BroadcastChannel('card');

// 监听'card'频道上的消息事件
channel.onmessage = function (event) {
   // 使用展开运算符将事件数据转换为视口坐标
   let [clientX, clientY] = screenToClient(...event.data);
   // 设置元素的left属性值,将视口的X坐标应用于card元素
   card.style.left = clientX + "px"; 
   // 设置元素的top属性值,将视口的Y坐标应用于card元素
   card.style.top = clientY + "px"; 
}

// 选择类名为.container 的元素
const card = document.querySelector('.container');
// 为选中的元素添加鼠标按下事件监听器
card.onmousedown = function (e) {
  // 计算鼠标指针在卡片元素上的相对偏移量
  const x = e.pageX - card.offsetLeft;
  const y = e.pageY - card.offsetTop;

  window.onmousemove = function (e) {
    // 根据相对偏移量和鼠标移动事件的坐标计算卡片新的位置
    let cx = e.pageX - x;
    let cy = e.pageY - y;
    // 设置卡片元素的新位置
    card.style.left = cx + "px";
    card.style.top = cy + "px";

    // 将卡片当前位置的坐标转换为屏幕坐标
    let points = clientToScreen(cx, cy);
    // 通过某个数据通道发送屏幕坐标信息
    channel.postMessage(points);
  }
  window.onmouseup = function () {
    // 释放鼠标时,取消鼠标移动和鼠标释放的事件监听器
    window.onmousemove = null;
    window.onmouseup = null;
  }
}

// 定义初始化函数 init
function init() {
    // 创建一个 URL 对象,用于解析当前窗口的 URL
    let url = new URL(window.location.href);
    // 使用 URL 对象的 searchParams 属性获取 URL 中的查询字符串参数 type
    let type = url.searchParams.get("type") || "a";

    // 判断 type 是否等于 a,如果是,将 card 元素的背景颜色设置为红色
    if (type === "a") {
        card.style.background = "red";
    } 
    // 判断 type 是否等于 b,如果是,将 card 元素的背景颜色设置为绿色
    else if (type === "b") {
        card.style.background = "green";
    } 
    // 判断 type 是否等于 c,如果是,将 card 元素的背景颜色设置为蓝色
    else if (type === "c") {
        card.style.background = "blue";
    }
}

// 调用 init 函数,启动初始化逻辑
init();
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 我们通过一个实战例子来学习屏幕坐标、窗口通信
  • 效果图
  • 完整代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档