import useWorker from "../lib/omnimatrix-video-player/omnimatrix-video-player.js";
import FingerprintJS from "../lib/FingerprintJS/fingerprint.min.js";
/**
* function useWorker(url: string, className: string, device: string, callback?: Function): any
@param url — wss连接地址 wss://origin/VideoShow/Common?UUID=uuid&DeviceID=deviceID&Token=token
@param className — 选择器 .video-class | #video-class ...
@param device — 设备ID
@param callback — 画面渲染完成时的回调
@returns — 包含两个Web Worker和一个关闭函数的对象
*/
/**
* @returns Promise
* @description 获取指纹
*/
function getFingerprint() {
return new Promise((resolve, reject) => {
// Get the visitor identifier when you need it.
FingerprintJS.load()
.then((fp) => fp.get())
.then((result) => {
// This is the visitor identifier:
const visitorId = result.visitorId;
resolve(visitorId);
})
.catch(reject);
});
}
// 格式化时间
function dateFormat(oDate, fmt) {
var o = {
"M+": oDate.getMonth() + 1, //月份
"d+": oDate.getDate(), //日
"h+": oDate.getHours(), //小时
"m+": oDate.getMinutes(), //分
"s+": oDate.getSeconds(), //秒
"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
S: oDate.getMilliseconds(), //毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
(oDate.getFullYear() + "").substr(4 - RegExp.$1.length)
);
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(
RegExp.$1,
RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
);
}
}
return fmt;
}
// 显示回调信息
function showCBInfo(szInfo) {
szInfo =
"
" +
dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") +
" " +
szInfo +
"
";
$("#cbinfo").html(szInfo + $("#cbinfo").html());
}
/**
* 获取ws连接地址
* @returns
*/
function getAddress(type = "Full", params = { X: 0, Y: 0 }) {
return `wss://${$("#Ip").val()}/VideoShow/Preview/${type}/Main?X=${
params.X
}&Y=${params.Y}`;
}
/**
* 重置画布
* @param {String} selector ——选择器
*/
function resetVideo(selector) {
let parent = $(selector).parent();
$(selector).remove();
parent.append(
``
);
}
/**
*
* @param {String} selector ——选择器
* @returns
*/
function getRatio(selector) {
return {
ratioX: $(selector).width() / $(selector).attr("width"),
ratioY: $(selector).height() / $(selector).attr("height"),
width: $(selector).width(),
baseWidth: $(selector).attr("width"),
baseHeight: $(selector).attr("height"),
};
}
/**
* 用于请求
* @param {String} url ——请求地址
* @param {String} method ——请求方式
* @param {Object} data ——请求参数
* @returns Promise
*/
function request(url, method = "GET", data = {}) {
return new Promise((resolve, reject) => {
$.ajax({
type: method,
url,
data,
dataType: "json",
timeout: 15000,
success: function (response) {
resolve(response);
},
error: function (error) {
reject(error);
},
});
});
}
// 滚轮缩放、放大逻辑
function enableImageManipulation(containerId, imageId, options = {}) {
const container = document.querySelector(containerId);
const image = document.querySelector(imageId);
let isDragging = false;
let startX,
startY,
initialX = 0,
initialY = 0,
scale = 1;
let currentX = 0,
currentY = 0,
targetX = 0,
targetY = 0;
// 配置选项: 最小和最大缩放比例,是否启用缩放和拖动功能
const minScale = options.minScale || container.offsetWidth / image.width;
const maxScale = options.maxScale || 3;
const dragSpeed = options.dragSpeed || 0.2;
const enableZoom = options.enableZoom !== false; // 默认启用缩放
const enableDrag = options.enableDrag !== false; // 默认启用拖动
// 处理缩放功能
if (enableZoom) {
container.addEventListener("wheel", function (event) {
event.preventDefault();
const { offsetX, offsetY } = event;
const delta = Math.sign(event.deltaY) * -0.1;
const newScale = Math.min(Math.max(scale + delta, minScale), maxScale);
const dx = (offsetX - currentX) * (newScale / scale - 1);
const dy = (offsetY - currentY) * (newScale / scale - 1);
scale = newScale;
currentX -= dx;
currentY -= dy;
updateImageTransform();
adjustPosition();
});
}
// 处理拖动功能
if (enableDrag) {
image.addEventListener("mousedown", function (event) {
isDragging = true;
startX = event.clientX;
startY = event.clientY;
const transform = image.style.transform.match(/translate\(([^)]+)\)/);
[initialX, initialY] = transform
? transform[1].split(",").map(parseFloat)
: [0, 0];
});
document.addEventListener("mousemove", function (event) {
if (isDragging) {
const dx = event.clientX - startX;
const dy = event.clientY - startY;
targetX = initialX + dx;
targetY = initialY + dy;
requestAnimationFrame(updateDrag);
}
});
function reset() {
isDragging = false;
}
document.addEventListener("mouseleave", reset);
document.addEventListener("mouseup", reset);
}
// 更新拖动的图像位置
function updateDrag() {
if (!isDragging) return;
currentX += (targetX - currentX) * dragSpeed;
currentY += (targetY - currentY) * dragSpeed;
updateImageTransform();
adjustPosition();
requestAnimationFrame(updateDrag);
}
// 更新图像的变换样式
function updateImageTransform() {
image.style.transform = `translate(${currentX}px, ${currentY}px) scale(${scale})`;
}
// 调整图像位置以限制在容器内
function adjustPosition() {
const rect = image.getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
let newX = rect.left - containerRect.left;
let newY = rect.top - containerRect.top;
if (rect.width < containerRect.width) {
newX = (containerRect.width - rect.width) / 2;
} else {
if (newX > 0) newX = 0;
if (newX + rect.width < containerRect.width)
newX = containerRect.width - rect.width;
}
if (rect.height < containerRect.height) {
newY = (containerRect.height - rect.height) / 2;
} else {
if (newY > 0) newY = 0;
if (newY + rect.height < containerRect.height)
newY = containerRect.height - rect.height;
}
currentX = newX;
currentY = newY;
updateImageTransform();
}
return () => {
isDragging = false;
startX = 0;
startY = 0;
initialX = 0;
initialY = 0;
scale = 1;
currentX = 0;
currentY = 0;
targetX = 0;
targetY = 0;
};
}
// 全屏方法
function fullScreenDisplay(dom) {
/* 全屏操作的主要方法和属性
* 不同浏览器需要添加不同的前缀
* chrome:webkit firefox:moz ie:ms opera:o
* 1.requestFullScreen():开启全屏显示
* 2.cancelFullScreen():退出全屏显示:在不同的浏览器下退出全屏只能使用document来实现
* 3.fullScreenElement:是否是全屏状态,也只能使用document进行判断
*/
// 判断是否全屏,全屏则退出,非全屏则全屏
if (
document.fullscreenElement ||
document.webkitFullscreenElement ||
document.mozFullScreenElement ||
document.msFullscreenElement
) {
if (document.cancelFullScreen) {
document.cancelFullScreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msCancelFullScreen) {
document.msCancelFullScreen();
}
} else {
dom
.requestFullscreen()
.then(() => {
// 进入全屏成功
})
.catch(() => {
// 进入全屏失败
});
}
}
const workerObj = {}; // 视频线程对象
const partObj = {}; // 获取的细节对象
let partActive = 1; // 细节框选中
let stateObj = {
qj: false,
part1: false,
part2: false,
}; // 全景录像状态
let partXY = {}; //双击全景的x y
let resetSF = null;
$(async function () {
// const fingerprint = await getFingerprint();
$("#controlgroup").controlgroup();
$("button").button();
$.each($("#controlgroup > input"), function (k, v) {
$(v).on("input", async () => {
$("#wsUrl").text(getAddress());
});
});
function jt(worker) {
worker && worker.postMessage({ type: "jt" });
}
function lx(WebSocketWork, type) {
stateObj[type] = !stateObj[type];
if (type === "qj") {
stateObj[type] ? showCBInfo(`全景开始录像`) : showCBInfo(`全景结束录像`);
} else {
stateObj[type] ? showCBInfo(`细节开始录像`) : showCBInfo(`细节结束录像`);
}
WebSocketWork &&
WebSocketWork.postMessage({
type: "lx",
lx: stateObj[type],
});
}
$("#wsUrl").text(getAddress());
$(".play-btn-qj").click(function () {
showCBInfo("全景播放");
if (workerObj["qj"]) {
$(".close-btn-qj").click();
}
let [ip = ""] = [$("#Ip").val()];
if (!ip) {
alert("请完善全局配置");
return;
}
$(".video-tip").show();
workerObj["qj"] = useWorker(getAddress(), "#video-demo", null, () => {
showCBInfo("全景播放完成");
$(".video-tip").hide();
});
function jtClick() {
showCBInfo(`全景开始截图`);
jt(workerObj["qj"].worker);
}
function lxClick() {
lx(workerObj["qj"].WebSocketWork, "qj");
$(this).toggleClass("lx-style");
}
// 关闭
$(".close-btn-qj").click(() => {
if (!workerObj["qj"]) return;
$(".jt-btn-qj").off("click");
$(".lx-btn-qj").off("click");
workerObj["qj"].close();
resetVideo("#video-demo");
workerObj["qj"] = null;
showCBInfo(`全景关闭`);
});
// 截屏
$(".jt-btn-qj").click(jtClick);
// 录像
$(".lx-btn-qj").click(lxClick);
// 双击全景
$(".panorama-box #video-demo").on("dblclick", function (e) {
showCBInfo("细节播放");
if (!workerObj["qj"]) return;
const closePart = (index) => {
if (!workerObj["part" + index]) return;
workerObj["part" + index].close();
resetVideo(`#video-demo${index}`);
workerObj["part" + index] = null;
showCBInfo(`关闭细节${partActive}`);
};
const { ratioX, ratioY, baseWidth, baseHeight } = getRatio(
".panorama-box #video-demo"
);
const mouseX = e.offsetX;
const mouseY = e.offsetY;
console.log("双击全景", mouseX, mouseY);
const params = {
X: `${mouseX / ratioX > baseWidth ? baseWidth : mouseX / ratioX}`,
Y: `${mouseY / ratioY > baseHeight ? baseHeight : mouseY / ratioY}`,
};
partXY[partActive] = params;
// 关闭细节
closePart(partActive);
$(`.video-tip${partActive}`).show();
workerObj["part" + partActive] = useWorker(
getAddress("Part", params),
`#video-demo${partActive}`,
null,
() => {
showCBInfo(`细节${partActive}播放完成`);
$(`.video-tip${partActive}`).hide();
resetSF = enableImageManipulation(
`.particulars-box .wheel${partActive}`,
`#video-demo${partActive}`,
{
enableZoom: true, // 启用缩放
enableDrag: true, // 启用拖动
minScale: 1, // 最小缩放比例
maxScale: 6, // 最大缩放比例
dragSpeed: 0.15, // 拖动速度
}
);
}
);
$.each($(".particulars-box-list>li"), function (i, v) {
$(v).find("button.close-btn-part").off("click");
$(v).find("button.lx-btn-part").off("click");
$(v).find("button.jt-btn-part").off("click");
$(v).off("mousedown");
$(v).off("mouseup");
let index = i + 1;
// 关闭
$(v)
.find("button.close-btn-part")
.click(function () {
closePart(index);
});
// 截图
$(v)
.find("button.jt-btn-part")
.click(() => {
showCBInfo(`细节开始截图`);
jt(workerObj["part" + index]?.worker);
});
// 录像
$(v)
.find("button.lx-btn-part")
.click(() => {
lx(workerObj["part" + index]?.WebSocketWork, "part" + index);
workerObj["part" + index] &&
$(v).find("button.lx-btn-part").toggleClass("lx-style");
});
});
});
});
$.each($(".particulars-box-list>li"), function (i, v) {
let index = i + 1;
$(v).click(function () {
if (index === partActive) return;
partActive = index;
$(".particulars-box-list>li").removeClass("active");
$(v).addClass("active");
});
$(`#video-demo${index}`)
.parent(".video-container")
.on("dblclick", function () {
resetSF();
$(`#video-demo${index}`).css("transform", "translate(0,0) scale(1)");
fullScreenDisplay(this);
});
});
});