Gahing's blog Gahing's blog
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Gahing / francecil

To be best
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前端基础

  • 应用框架

  • 工程能力

  • 应用基础

  • 专业领域

    • 服务端

    • 跨端技术

    • Web IDE

    • 中后台

    • 动效渲染

    • 可视化

    • 埋点监控

    • 多媒体

      • 业务场景

        • 云游戏

          • video标签下触摸坐标归一化
            • 基本知识
              • 触摸点位置
              • 触摸事件
              • PC
              • Mobile
              • 全屏
              • 进入全屏
              • 退出全屏
              • 判断是否全屏
              • 监听手机横竖屏状态
              • 竖屏0 横屏 90(正常横放) -90 (手机顶部在右侧)
              • CSS3旋转元素
              • 注意:全屏状态下元素的旋转效果无效
              • video元素
              • 属性详解
              • body在移动端显示时左侧会留出一定宽度的竖条,设置100%页没有用
            • Touch事件捕获
              • 基本方法
              • 屏幕分辨率
              • 横屏下 window.screen.width 得到的 手机的高度的那个分辨率而不是宽度
              • 发送touch事件方法——sendTouchEvent
              • 为什么考虑源数据横竖屏情况?
        • 直播

      • 基础知识

    • 桌面技术

    • 游戏互动

    • 编辑器

    • 虚拟化与容器化

    • 设计系统

  • 业务场景

  • 大前端
  • 专业领域
  • 多媒体
  • 业务场景
  • 云游戏
gahing
2016/08/24
目录

video标签下触摸坐标归一化

# 基本知识

# 触摸点位置

  • clientX / clientY:// 触摸点相对于浏览器窗口viewport的位置 参照点会随着浏览器的滚动而变化
  • pageX / pageY:// 触摸点相对于页面的位置 参照点不会随着浏览器的滚动而变化
  • screenX /screenY:// 触摸点相对于屏幕的位置

所以如果要算鼠标在当前div的相对位置

通过获取var offset = $("#mainScreen").offset();后

当前鼠标的绝对位置要用 pageX/Y 去拿 否则浏览器页面滚动后会少算一段

# 触摸事件

# PC

onmousemove	script	当鼠标指针移动到元素上时触发。
onmouseout	script	当鼠标指针移出元素时触发。
onmouseup 属性在松开鼠标按钮时触发。
提示:相对于 onmouseup 事件的事件次序(限于鼠标左/中键):
onmousedown
onmouseup
onclick
onmouseup 事件的事件次序(限于鼠标右键):
onmousedown
onmouseup
oncontextmenu
onMouseover和onMousemove有什么区别?
区别是进入后onmousemove鼠标每动一下都会执行事件,onmouseover只在鼠标进入时执行一次

# Mobile

基本事件如下,其他的都是对这些事件的组合封装

mainScreen.addEventListener("touchmove", touchMove, false);//手指在屏幕上移动时触发[不动但停留太久也会触发]
mainScreen.addEventListener("touchstart", touchStart, false);//手指一触摸屏幕就触发
mainScreen.addEventListener("touchend", touchEnd, false);//手指离开屏幕触发
1
2
3

# 全屏

# 进入全屏

function launchFullScreen (element) {
  if (element.requestFullscreen) {
    element.requestFullscreen();
  } else if (element.mozRequestFullScreen) {
    element.mozRequestFullScreen();
  } else if (element.webkitRequestFullscreen) {
    element.webkitRequestFullscreen();
  } else if (element.msRequestFullscreen) {
    element.msRequestFullscreen();
  }
}
1
2
3
4
5
6
7
8
9
10
11

# 退出全屏

function cancelFullScreen () {
  if (document.cancelFullScreen) {
    document.cancelFullScreen();
  } else if (document.mozCancelFullScreen) {
    document.mozCancelFullScreen();
  } else if (document.webkitCancelFullScreen) {
    document.webkitCancelFullScreen();
  }
}
1
2
3
4
5
6
7
8
9

# 判断是否全屏

//反射調用
var invokeFieldOrMethod = function (element, method) {
  var usablePrefixMethod;
  ["webkit", "moz", "ms", "o", ""].forEach(function (prefix) {
    if (usablePrefixMethod) return;
    if (prefix === "") {
      // 无前缀,方法首字母小写
      method = method.slice(0, 1).toLowerCase() + method.slice(1);
    }
    var typePrefixMethod = typeof element[prefix + method];
    if (typePrefixMethod + "" !== "undefined") {
      if (typePrefixMethod === "function") {
        usablePrefixMethod = element[prefix + method]();
      } else {
        usablePrefixMethod = element[prefix + method];
      }
    }
  });

  return usablePrefixMethod;
}
//判断是否是全屏
function isFullScreen () {
  return invokeFieldOrMethod(document, 'FullScreen') || invokeFieldOrMethod(document, 'IsFullScreen') || document.IsFullScreen;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 监听手机横竖屏状态

var mOrientation = 0;
$(window).on("orientationchange", function () {
  mOrientation = window.orientation;
  if (window.orientation == 0) // Portrait
  {
    console.log("竖屏状态");
  } else // Landscape
  {
    console.log("横屏状态");
  }
});
1
2
3
4
5
6
7
8
9
10
11

# 竖屏0 横屏 90(正常横放) -90 (手机顶部在右侧)

# CSS3旋转元素

.trans90 {
  /* Rotate div */
  transform: rotate(9deg);
  -ms-transform: rotate(90deg);
  /* Internet Explorer */
  -moz-transform: rotate(90deg);
  /* Firefox */
  -webkit-transform: rotate(90deg);
  /* Safari 和 Chrome */
  -o-transform: rotate(90deg);
  /* Opera */
}
1
2
3
4
5
6
7
8
9
10
11
12
function transfVideo () {
  $("#remoteVideo").addClass("trans90");
}
1
2
3

# 注意:全屏状态下元素的旋转效果无效

# video元素

<video id="remoteVideo" autoplay width="100%" height="100%">
	<p>您的浏览器不支持该标签</p>
</video>

# 属性详解

  • autoplay :自动播放
  • width="100%" height="100%" :设置元素的宽高,非源数据的宽高

不指定controls 属性,则不会显示默认的播放,进度条等样式,但是全屏时又会显示,怎么去掉?

参考https://segmentfault.com/a/1190000000380064 (opens new window)

/*伪元素,设置全屏时不显示控件*/
video::-webkit-media-controls-enclosure {
  display: none;
}
video::-moz-media-controls-enclosure {
  display: none;
}
video::media-controls-enclosure {
  display: none;
}
1
2
3
4
5
6
7
8
9
10
  • videoWidth,videoHeight属性:指的是视频源数据,不会改变,也不能修改。
  • width,height属性:video容器大小,当其值设置的与视频源数据不同时,会将视频源数据进行一定比例(videoWidth,videoHeight的比例)的缩放,使得视频数据尽量充满video容器

# body在移动端显示时左侧会留出一定宽度的竖条,设置100%页没有用

移动端会留与滚动条有关,改margin就行

body {
  width: 100%;
  height: 100%;
  margin: 0px;
  background-color: white;
}
1
2
3
4
5
6

# Touch事件捕获

# 基本方法

function touchMove(event) {
  event.preventDefault();
  if(!event.touches.length) return;
  var touch = event.touches[0];
  sendTouchEvent(touch, "TOUCH_MOVE");
};

function touchStart(event) {
  event.preventDefault();
  if(!event.touches.length) return;
  var touch = event.touches[0];
  sendTouchEvent(touch, "TOUCH_START");

};

function touchEnd() {
  console.log("type:end");
}

mainScreen.addEventListener("touchmove", touchMove, false);
mainScreen.addEventListener("touchstart", touchStart, false);
mainScreen.addEventListener("touchend", touchEnd, false);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 屏幕分辨率

console.log(" 屏幕分辨率的高:" + window.screen.height + "\n" + " 屏幕分辨率的宽:" + window.screen.width + "\n")
1

# 横屏下 window.screen.width 得到的 手机的高度的那个分辨率而不是宽度

# 发送touch事件方法——sendTouchEvent

如果要考虑完全的话,需要考虑12种情况

3种屏幕方向*是否全屏2种情况*源数据横竖屏情况(宽高比)2种情况=12

# 为什么考虑源数据横竖屏情况?

进行坐标映射、归一化的时候你就知道了

是否全屏下,video都要自动充满屏幕(videoWidth:videoHeight不变)

其video容器的宽度要保持和window.screen.width一致

代码如下 目前只考虑以下6种情况,其他情况为非法操作

  1. 竖屏*是否全屏(2种)*源数据横竖屏(2种)

  2. 横屏(90和-90两种情况)*全屏*源数据横屏

function sendTouchEvent (touch, eventType) {
  //videoWidth、videoHeight、width和height的大小切屏不会改变大小
  //暂不考虑非全屏时横屏坐标 0 90(正常横放) -90 (机顶在右侧)
  //全屏模式下 touch.pageX/Y 不用参考offset
  trace(mOrientation);
  var remoteVideo = document.getElementById("remoteVideo");
  //暂不考虑videoWidth>videoHeight时mOrientation == 0的全屏情况
  if (mOrientation == 0) {
    var currentWidth = remoteVideo.width;
    var currentHeight = (remoteVideo.width / remoteVideo.videoWidth * remoteVideo.videoHeight);
    //						trace("当前总宽度" + currentWidth + "当前总高度:" + currentHeight);
    var relativeX = (touch.pageX - offset.left);
    var relativeY = (touch.pageY - offset.top);
    //判断是否为全屏 全屏下位置为 touch.pageY-(window.screen.height-currentWidth)/2
    var posX = relativeX;
    if (isFullScreen()) {
      //全屏情况下要考虑videoWidth>videoHeigh
      if (remoteVideo.videoWidth <= remoteVideo.videoHeight) {
        //console.log("touch.pageY:"+touch.pageY+" window.screen.height:"+window.screen.height+" remoteVideo.videoHeight:"+remoteVideo.videoHeight+" relativeY:"+relativeY);
        var posY = (touch.pageY - (window.screen.height - currentHeight) / 2);
        //console.log("x:" + relativeX + " y:" + posY+ " type:"+eventType+" full");
        var floatX = posX < 0 ? 0 : (posX > currentWidth ? 1 : posX / currentWidth);
        var floatY = posY < 0 ? 0 : (posY > currentHeight ? 1 : posY / currentHeight);
        console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
        trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      } else {
        var posY = relativeX;
        var posX = currentHeight - (touch.pageY - (window.screen.height - currentHeight) / 2);
        var floatX = posX < 0 ? 0 : (posX > currentHeight ? 1 : posX / currentHeight);
        var floatY = posY < 0 ? 0 : (posY > currentWidth ? 1 : posY / currentWidth);
        console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
        trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      }
    } else {
      //console.log("x:" + relativeX + " y:" + relativeY + " type:"+eventType+" nofull");
      if (remoteVideo.videoWidth <= remoteVideo.videoHeight) {
        var posY = relativeY;
        var floatX = posX < 0 ? 0 : (posX > currentWidth ? 1 : posX / currentWidth);
        var floatY = posY < 0 ? 0 : (posY > currentHeight ? 1 : posY / currentHeight);
        console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
        trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      } else {
        var posY = relativeX;
        var posX = currentHeight - relativeY;
        var floatX = posX < 0 ? 0 : (posX > currentHeight ? 1 : posX / currentHeight);
        var floatY = posY < 0 ? 0 : (posY > currentWidth ? 1 : posY / currentWidth);
        console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
        trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      }

    }

  } else if (mOrientation == 90) {
    //目前只考虑全屏的情况
    //width和height说法还是和手机保持一致 不受影响
    //videoWidth、videoHeight、width和height的大小与横屏时保持一致 640 480
    var currentWidth = remoteVideo.width;
    var currentHeight = (remoteVideo.videoWidth / remoteVideo.videoHeight) * remoteVideo.width;
    //						trace("当前总宽度" + currentWidth + "当前总高度:" + currentHeight);//360 480
    //						trace("touch.pageX:"+touch.pageX+" touch.pageY:"+touch.pageY);
    var posX = currentWidth - touch.pageY;
    //横屏下 window.screen.width得到的 手机的高度的那个分辨率而不是宽度
    var posY = touch.pageX - (window.screen.width - currentHeight) / 2;
    //还得考虑videoHeight>videoWidth,非全屏的情况 这边不写了
    if (isFullScreen()) {
      //							trace("posX:"+posX+" posY"+posY);
      //							trace("touch.pageX:"+touch.pageX+" window.screen.width:"+window.screen.width+" currentHeight:"+currentHeight);
      var floatX = posX < 0 ? 0 : (posX > currentWidth ? 1 : posX / currentWidth);
      var floatY = posY < 0 ? 0 : (posY > currentHeight ? 1 : posY / currentHeight);
      console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
    }
  } else if (mOrientation == -90) {
    var currentWidth = remoteVideo.width;
    var currentHeight = (remoteVideo.videoWidth / remoteVideo.videoHeight) * remoteVideo.width;
    var posX = currentWidth - touch.pageY;
    //需要window.screen.width去减
    var posY = touch.pageX - (window.screen.width - currentHeight) / 2;
    //还得考虑videoHeight>videoWidth的情况 这边不写了
    if (isFullScreen()) {
      //							trace("posX:"+posX+" posY"+posY);
      //							trace("touch.pageX:"+touch.pageX+" window.screen.width:"+window.screen.width+" currentHeight:"+currentHeight);
      var floatX = posX < 0 ? 0 : (posX > currentWidth ? 1 : posX / currentWidth);
      var floatY = posY < 0 ? 0 : (posY > currentHeight ? 1 : posY / currentHeight);
      console.log("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
      trace("发送结果:横坐标:" + floatX + " 纵坐标" + floatY + "类型:" + eventType);
    }
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
编辑 (opens new window)
#多点触控#HTML
上次更新: 2025/06/11, 23:06:59
埋点方案介绍(代码、可视化、无痕)
TryPlay_Android_架构

← 埋点方案介绍(代码、可视化、无痕) TryPlay_Android_架构→

最近更新
01
我的 2024 总结
12-31
02
浅谈代码质量与量化指标
08-27
03
快速理解 JS 装饰器
08-26
更多文章>
Theme by Vdoing | Copyright © 2016-2025 Gahing | 闽ICP备19024221号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式