pixelstream-cn
Version:
基于虚幻引擎的像素流平台
346 lines (305 loc) • 12.2 kB
JavaScript
'use strict';
import TouchEventHandler from './TouchEventHandler';
export default class player {
constructor(tools,keyboard,mode,mouseSimulate) {
if(mouseSimulate!=null){
this.touchEventHandler = new TouchEventHandler(mouseSimulate);
}
this.keyboardDowns={};
this.mouseDowns={};
this.keyboard=null;
this.tools=tools;
this.mode=mode;
this.setKeyboard(keyboard);
this.isFocus=false; // 是焦点? 焦点状态下才可以输入键盘信息
}
setKeyboard(keyboard){
this.keyboard = keyboard;
}
init(element) {
let videoDiv = document.createElement("div");
videoDiv.style.position="absolute";
videoDiv.style.outline="none";
this.videoElement = document.createElement("video");
// this.videoElement.controls=true;
this.videoElement.style.width="100%";
this.videoElement.style.height="100%";
this.videoElement.playsInline = true;
this.videoElement.autoplay=true;
this.videoElement.muted=true;
videoDiv.append(this.videoElement);
let mouseDiv = document.createElement("div");
mouseDiv.style.height="100%";
mouseDiv.style.width="100%";
mouseDiv.style.position="absolute";
// mouseDiv.style.zIndex=9999;
if(this.mode=='stretch'){
videoDiv.style.height="100%";
videoDiv.style.width="100%";
this.videoElement.style.objectFit="fill";
}else{
videoDiv.style.width="100%";
}
element.append(videoDiv);
if(this.tools){
let toolElement = document.createElement("div");
toolElement.style.height="20px";
toolElement.style.position="absolute";
toolElement.style.zIndex=9999;
toolElement.style.top="20px";
toolElement.style.left="20px";
toolElement.style.background="#000";
toolElement.style.color="#fff";
toolElement.style.lineHeight="12px";
toolElement.style.fontSize="12px";
toolElement.style.padding="4px";
toolElement.style.cursor="pointer";
toolElement.style.boxSizing="border-box";
toolElement.innerHTML="锁定鼠标";
toolElement.addEventListener("click",()=>{
videoDiv.requestPointerLock();
});
element.append(toolElement);
}
this.mouseElement = videoDiv;
if(this.touchEventHandler){
this.touchEventHandler.setTargetElement(this.mouseElement);
}
this.initPlayer();
}
audio(stream){
console.log("audio");
this.audioElem = document.createElement("Audio");
this.audioElem.srcObject = stream;
}
playAudio(){
try {
this.audioElem.play();
console.log("playAudio");
} catch (error) {
console.log("playAudio fail");
setTimeout(this.playAudio,500);
}
}
play(stream) {
this.isPlaying = false;
this.videoElement.srcObject = stream;
this.videoElement.load();
let _this = this;
this.videoElement.addEventListener('loadedmetadata', (e) => {
_this.playAudio();
// _this.setPlayerSize(_this.videoElement.videoWidth, _this.videoElement.videoHeight);
});
}
// setPlayerSize(videoWidth, videoHeight) {
// console.log("setPlayerSize",videoWidth, videoHeight);
// let radio = this.mouseElement.offsetWidth/videoWidth;
// console.log("radio",radio);
// }
initPlayer() {
this.fingers = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0];
this.fingerIds = {};
let _this = this
// this.mouseElement.onfocus = ()=>{
// console.log("onfocus");
// this.isFocus=true;
// }
// this.mouseElement.onblur = ()=>{
// console.log("onblur");
// this.isFocus=false;
// }
// this.mouseElement.setAttribute('tabindex', '0');
this.mouseElement.onmousedown = (e) => {
_this.mouseElement.focus();
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseDownHandel(e.button,coord);
_this.mouseDowns[e.button]=e;
e.preventDefault();
}
this.mouseElement.onmouseup = (e) => {
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseUpHandel(e.button,coord);
delete _this.mouseDowns[e.button];
// e.preventDefault();
};
this.mouseElement.onmousemove = (e) => {
_this.isFocus=true;
// offsetX 为正 为负 offsetY 为正 为负
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
let delta = _this.normalizeAndQuantizeSigned(e.movementX, e.movementY);
_this.mouseMoveHandel(coord,delta);
e.preventDefault();
}
this.mouseElement.onmouseenter = function (e) {
_this.mouseEnterHandel(e);
// _this.mouseElement.pressMouseButtons(e);
e.preventDefault();
};
this.mouseElement.onmouseleave = (e)=>{
_this.isFocus=false;
for(let key in _this.mouseDowns){
_this.mouseElement.onmouseup(_this.mouseDowns[key]);
delete _this.mouseDowns[key];
}
for(let key in _this.keyboardDowns){
_this.keyboardUpHandel(_this.keyboardDowns[key]);
delete _this.keyboardDowns[key];
}
_this.mouseLeaveHandel(e);
_this.mouseElement.releaseMouseButtons(e);
e.preventDefault();
};
this.mouseElement.pressMouseButtons = (e) => {
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mousePressHandel(e.buttons,coord);
}
this.mouseElement.releaseMouseButtons = (e) => {
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseReleaseHandel(e.buttons,coord);
}
this.videoElement.ontouchstart = (e)=>{
console.log("ontouchstart",e)
_this.isFocus=true;
if(_this.touchEventHandler){
_this.touchEventHandler.handleTouchStart(e);
}else{
for (let t = 0; t < e.changedTouches.length; t++) {
_this.rememberTouch(e.changedTouches[t]);
}
_this.touchStartHandel(_this.getTouchData(e.changedTouches),);
}
e.preventDefault();
}
this.videoElement.ontouchend = function(e) {
console.log("ontouchend")
_this.isFocus=true;
if(_this.touchEventHandler){
_this.touchEventHandler.handleTouchEnd(e);
}else{
_this.touchEndHandel(_this.getTouchData(e.changedTouches));
// Re-cycle unique identifiers previously assigned to each touch.
for (let t = 0; t < e.changedTouches.length; t++) {
_this.forgetTouch(e.changedTouches[t]);
}
}
e.preventDefault();
};
this.videoElement.ontouchmove = function(e) {
console.log("ontouchmove")
if(_this.touchEventHandler){
_this.touchEventHandler.handleTouchMove(e);
}else{
_this.touchMoveHandel(_this.getTouchData(e.touches));
}
e.preventDefault();
};
this.mouseElement.addEventListener('contextmenu', (e) => {
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseUpHandel(e.button,coord);
e.preventDefault();
})
document.onkeydown = function(e) {
if(_this.isFocus){
if(!_this.keyboard || _this.keyboard.findIndex(item=>{return item.toLowerCase()==e.key.toLowerCase()})>=0){
_this.keyboardDowns[e.key]=e;
_this.keyboardDownHandel(e);
e.preventDefault(); //preventDefault 用来阻断后续事件 如keypress
}
}
}
document.onkeyup = function(e) {
if(_this.isFocus){
if(!_this.keyboard || _this.keyboard.findIndex(item=>{return item.toLowerCase()==e.key.toLowerCase()})>=0){
if(_this.keyboardDowns[e.key]){
delete _this.keyboardDowns[e.key];
}
_this.keyboardUpHandel(e);
e.preventDefault();
}
}
}
document.onkeypress = function(e) {
if(_this.isFocus){
if(!_this.keyboard || _this.keyboard.findIndex(item=>{return item.toLowerCase()==e.key.toLowerCase()})>=0){
_this.keyboardPressHandel(e);
e.preventDefault();
}
}
}
if ('onmousewheel' in this.mouseElement) {
this.mouseElement.onmousewheel = (e) => {
_this.mouseElement.focus();
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseWheelHandel(e.wheelDelta, coord);
e.preventDefault();
}
} else {
this.mouseElement.addEventListener(
'DOMMouseScroll',
(e) => {
_this.mouseElement.focus();
let coord = _this.normalizeAndQuantizeUnsigned(e.offsetX, e.offsetY);
_this.mouseWheelHandel(e.detail * -120, coord);
e.preventDefault();
},
false
)
}
}
getTouchData(touches) {
let data = [];
for (let t = 0; t < touches.length; t++) {
let touch = touches[t];
let x = touch.clientX - this.getOffsetLeft(touch.target);
let y = touch.clientY - this.getOffsetTop(touch.target);
let coord = this.normalizeAndQuantizeUnsigned(x, y);
data.push({
coord:coord,
finger:this.fingerIds[touch.identifier],
force:touch.force,
});
}
return data;
}
getOffsetLeft(target){
if(target.offsetParent){
return target.offsetLeft+this.getOffsetLeft(target.offsetParent);
}
return target.offsetLeft;
}
getOffsetTop(target){
if(target.offsetParent){
return target.offsetTop+this.getOffsetTop(target.offsetParent);
}
return target.offsetTop;
}
rememberTouch(touch) {
let finger = this.fingers.pop();
this.fingerIds[touch.identifier] = finger;
}
forgetTouch(touch) {
this.fingers.push(this.fingerIds[touch.identifier]);
delete this.fingerIds[touch.identifier];
}
normalizeAndQuantizeUnsigned(x, y) {
let widthRatio = x / this.mouseElement.clientWidth; //0-1之间占比
let heightRatio = y / this.mouseElement.clientHeight; //0-1之间占比
let normalizedX = widthRatio;
let normalizedY = heightRatio;
return {
inRange: true,
x: normalizedX * 65536,
y: normalizedY * 65536,
}
}
normalizeAndQuantizeSigned(x, y) {
let widthRatio = x / (this.mouseElement.clientWidth / 2); //0-1之间占比
let heightRatio = y / (this.mouseElement.clientHeight / 2); //0-1之间占比
let normalizedX = widthRatio;
let normalizedY = heightRatio;
return {
x: normalizedX * 32767,
y: normalizedY * 32767,
}
}
}