@jxstjh/jhvideo
Version:
HTML5 jhvideo base on MPEG2-TS Stream Player
492 lines • 22.4 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { fabric } from 'fabric';
import { EventEmitter } from 'events';
var finishIcon = "data:image/svg+xml;base64,PHN2Zw0KICAgICAgICB0PSIxNjY1OTc1ODY3NzczIg0KICAgICAgICBjbGFzcz0iaWNvbiINCiAgICAgICAgdmlld0JveD0iMCAwIDEwMjQgMTAyNCINCiAgICAgICAgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEwMzQ2IiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+DQogICAgPHBhdGggZD0iTTc3Mi4yNjY2NjcgMzU2LjI2NjY2N2wtMzU5LjY4IDM2MC45NmEzNC45ODY2NjcgMzQuOTg2NjY3IDAgMCAxLTguNTMzMzM0IDYuODI2NjY2IDM1Ljg0IDM1Ljg0IDAgMCAxLTQ5LjA2NjY2Ni0xMy42NTMzMzNsLTEwOS4yMjY2NjctMTkwLjI5MzMzM2EzNS44NCAzNS44NCAwIDAgMSA2Mi4yOTMzMzMtMzUuODRsODUuMzMzMzM0IDE0OS4zMzMzMzMgMzI3LjY4LTMyOC41MzMzMzNhMzUuODQgMzUuODQgMCAwIDEgNTEuMiA1MC43NzMzMzN6TTUxMiAwYTUxMiA1MTIgMCAxIDAgNTEyIDUxMkE1MTIgNTEyIDAgMCAwIDUxMiAweiINCiAgICAgICAgICBmaWxsPSIjZmYyYTAwIiBwLWlkPSIxMDM0NyI+DQogICAgPC9wYXRoPg0KPC9zdmc+DQo=";
var rectangleDefault = [{ x: 0.001, y: 0.001 }, { x: 0.998, y: 0.001 }, { x: 0.998, y: 0.998 }, { x: 0.001, y: 0.998 }];
// 矩形框绘制
var rectDraw = /** @class */ (function () {
function rectDraw(videoDom, cardId, dom) {
this.drawing = false;
this.proportion = [];
this.initialPoint = [];
this.style = {
color: 'rgba(255, 42, 0, .9)',
border: 'rgba(255, 42, 0, .4)',
strokeWidth: 2
};
var rectangle = dom[0], fabricDom = dom[1];
this.cardID = cardId;
this.rectangle = rectangle;
this.fabricDom = fabricDom;
videoDom.appendChild(rectangle);
this.emitter = new EventEmitter();
/* const handleIcon = (eventData, transform) => {
this.emitter.emit('complete')
}
const finishImg = document.createElement('img')
finishImg.src = finishIcon
fabric.Object.prototype.controls.deleteControl = new fabric.Control({
x: 0.5,
y: -0.5,
offsetY: -15,
offsetX: 15,
cursorStyle: 'pointer',
mouseUpHandler: handleIcon,
render: this.renderIcon(finishImg),
cornerSize: 18
}) */
}
// 确认图标
rectDraw.prototype.renderIcon = function (icon) {
return function (ctx, left, top, styleOverride, fabricObject) {
var size = this.cornerSize;
ctx.save();
ctx.translate(left, top);
ctx.rotate(fabric.util.degreesToRadians(fabricObject.angle));
ctx.drawImage(icon, -size / 2, -size / 2, size, size);
ctx.restore();
};
};
rectDraw.prototype.on = function (event, listener) {
this.emitter.addListener(event, listener);
};
rectDraw.prototype.off = function (event, listener) {
this.emitter.removeListener(event, listener);
};
/*创建绘画/编辑绘画*/
rectDraw.prototype.begin = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.drawing = true;
this.rectangle.style.zIndex = '9';
this.drawType('polygon');
// 赋值初始值
this.initialPoint = __spreadArray([], this.proportion, true);
return [2 /*return*/];
});
});
};
rectDraw.prototype.setDom = function (width, height) {
if (this.canvas) {
this.canvas.dispose();
this.canvas = undefined;
}
this.fabricDom.width = width;
this.fabricDom.height = height;
this.canvas = new fabric.Canvas(this.cardID, {
uniformScaling: false,
preserveObjectStacking: true
});
this.setInfo();
};
rectDraw.prototype.setInfo = function () {
/*
const canvasMouseDown = (e) => {
this.downObject = e
this.downPoint = e.absolutePointer
}
const canvasMouseUp = (e) => {
if (this.currentType === 'rect') {
// 创建矩形
createRect(e.absolutePointer)
}
}
// 创建矩形
const createRect = (pointer) => {
const {downPoint, canvas, style} = this
// 矩形参数计算
const top = Math.min(downPoint.y, pointer.y)
const left = Math.min(downPoint.x, pointer.x)
const width = Math.abs(downPoint.x - pointer.x)
const height = Math.abs(downPoint.y - pointer.y)
// 矩形对象
const rect = new fabric.Rect({
top,
left,
width,
height,
fill: 'transparent',
strokeWidth: style.strokeWidth,
stroke: style.color,
scaleX: 1,
scaleY: 1,
strokeUniform: true, // 变形后保持宽度
objectCaching: false // 高速缓存,可在变形时减少虚化
})
// 将矩形添加到画布上
rect.setControlsVisibility({mtr: false}) // 取消旋转手柄
canvas.add(rect)
this.downPoint = null
if (canvas.getObjects().length > 0) {
this.drawType('select')
}
}
this.canvas.on('mouse:down', canvasMouseDown) // 鼠标在画布上按下
this.canvas.on('mouse:up', canvasMouseUp) // 鼠标在画布上松开
*/
var _this = this;
// 双击事件
var canvasDlclick = function (e) {
var ePointer = e.pointer;
var oCoords = e.target.oCoords;
var polygons = e.target.points;
var offsetX = oCoords.p0.x - polygons[0].x;
var offsetY = oCoords.p0.y - polygons[0].y;
var offsetPointer = {
x: ePointer.x - offsetX,
y: ePointer.y - offsetY
};
// 双击位置是否与点重叠
var index = polygons.reduce(function (prv, v, i) {
if (v.x + 3 > offsetPointer.x && offsetPointer.x > v.x - 3 && v.y + 3 > offsetPointer.y && offsetPointer.y > v.y - 3) {
prv = i;
}
return prv;
}, -1);
// 添加~删除~点
if (index < 0) {
// 添加点
var integers = polygons.map(function (v) {
return {
x: ~~v.x,
y: ~~v.y
};
});
var operateObj = pointIsAdd(offsetPointer, integers);
if (operateObj) {
polygons.splice(operateObj.index, 0, offsetPointer);
_this.drawType('polygon');
}
}
else if (polygons.length > 3) {
// 删除点
polygons.splice(index, 1);
_this.drawType('polygon');
}
// 判断是否有添加点
function pointIsAdd(point, segments) {
var mistake = [];
for (var i = 1; i < segments.length + 1; i++) {
var ps = segments[i - 1];
var pe = i === segments.length ? segments[0] : segments[i];
var extent = distanceOfPointAndLine(ps.x, ps.y, pe.x, pe.y, point.x, point.y);
// 距离在2.5之内
if (extent < 2.5) {
mistake.push({
extent: extent,
pStart: ps,
pEnd: pe,
index: i
});
}
}
if (mistake.length > 0) {
return mistake.reduce(function (prv, cur) {
return prv.extent < cur.extent ? prv : cur;
}, mistake[0]);
}
return null;
}
// 点到线段距离
function distanceOfPointAndLine(x1, y1, x2, y2, x, y) {
var A = x - x1;
var B = y - y1;
var C = x2 - x1;
var D = y2 - y1;
var dot = A * C + B * D;
var len_sq = C * C + D * D;
var param = -1;
if (len_sq != 0) { //线段长度不能为0
param = dot / len_sq;
}
var xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
}
else if (param > 1) {
xx = x2;
yy = y2;
}
else {
xx = x1 + param * C;
yy = y1 + param * D;
}
var dx = x - xx;
var dy = y - yy;
return Math.sqrt(dx * dx + dy * dy);
}
};
this.canvas.on('mouse:dblclick', canvasDlclick);
this.rectangle.style.zIndex = '1';
// 有参数时自动绘制
if (this.proportion.length > 0) {
this.resetRect();
}
};
// 绘画多边形
rectDraw.prototype.resetRect = function () {
var _a = this, canvas = _a.canvas, style = _a.style, proportion = _a.proportion;
var _b = this.fabricDom, clientHeight = _b.clientHeight, clientWidth = _b.clientWidth;
canvas.remove(canvas.getActiveObject());
var points = proportion.map(function (v) {
return {
x: v.x * clientWidth,
y: v.y * clientHeight
};
});
var polygon = new fabric.Polygon(points, {
fill: 'transparent',
strokeWidth: style.strokeWidth,
stroke: style.color,
scaleX: 1,
scaleY: 1,
objectCaching: false,
transparentCorners: false,
cornerColor: 'blue',
});
canvas.add(polygon);
/*const {canvas, proportion, style} = this
const {clientHeight, clientWidth} = this.fabricDom
const {x, y, width, height} = proportion
const rect = new fabric.Rect({
top: y * clientHeight,
left: x * clientWidth,
width: width * clientWidth,
height: height * clientHeight,
fill: 'transparent',
strokeWidth: style.strokeWidth,
stroke: style.color,
scaleX: 1,
scaleY: 1,
strokeUniform: true, // 变形后保持宽度
objectCaching: false // 高速缓存,可在变形时减少虚化
})
rect.setControlsVisibility({mtr: false})
canvas.add(rect)*/
this.drawType('');
};
rectDraw.prototype.drawType = function (type) {
this.currentType = type;
var _a = this, canvas = _a.canvas, style = _a.style;
switch (type) {
case '':
canvas.selection = false;
canvas.skipTargetFind = true;
break;
case 'select':
canvas.selection = true;
canvas.selectionColor = 'rgba(255, 255, 255, 0.01)';
canvas.selectionBorderColor = 'rgba(255, 255, 255, 0.5)';
canvas.skipTargetFind = false; // 允许选中
break;
case 'rect':
canvas.selectionColor = 'transparent';
canvas.selectionBorderColor = style.border;
canvas.skipTargetFind = true; // 禁止选中
break;
case 'polygon':
polygonEdit();
canvas.skipTargetFind = false;
break;
}
// 定义一个可以定位控件的函数.
// 该函数将用于绘图和交互.
function polygonPositionHandler(dim, finalMatrix, fabricObject) {
var x = (fabricObject.points[this.pointIndex].x - fabricObject.pathOffset.x), y = (fabricObject.points[this.pointIndex].y - fabricObject.pathOffset.y);
return fabric.util.transformPoint({ x: x, y: y }, fabric.util.multiplyTransformMatrices(fabricObject.canvas.viewportTransform, fabricObject.calcTransformMatrix()));
}
function getObjectSizeWithStroke(object) {
var stroke = new fabric.Point(object.strokeUniform ? 1 / object.scaleX : 1, object.strokeUniform ? 1 / object.scaleY : 1).multiply(object.strokeWidth);
return new fabric.Point(object.width + stroke.x, object.height + stroke.y);
}
// 定义一个函数,该函数将定义控件的作用
// 该函数将在每次鼠标移动时调用
// 单击并正在拖动
// 函数接收鼠标事件作为参数,当前transformat对象
// 以及画布坐标中的当前位置
// transform.target是对正在转换的当前对象的引用,
function actionHandler(eventData, transform, x, y) {
var polygon = transform.target, currentControl = polygon.controls[polygon.__corner], mouseLocalPosition = polygon.toLocalPoint(new fabric.Point(x, y), 'center', 'center'), polygonBaseSize = getObjectSizeWithStroke(polygon), size = polygon._getTransformedDimensions(0, 0), finalPointPosition = {
x: mouseLocalPosition.x * polygonBaseSize.x / size.x + polygon.pathOffset.x,
y: mouseLocalPosition.y * polygonBaseSize.y / size.y + polygon.pathOffset.y
};
polygon.points[currentControl.pointIndex] = finalPointPosition;
return true;
}
// 定义一个函数,该函数可以在我们更改其
// width/height/top/left.
function anchorWrapper(anchorIndex, fn) {
return function (eventData, transform, x, y) {
var fabricObject = transform.target, absolutePoint = fabric.util.transformPoint({
x: (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x),
y: (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y),
}, fabricObject.calcTransformMatrix()), actionPerformed = fn(eventData, transform, x, y), newDim = fabricObject._setPositionDimensions({}), polygonBaseSize = getObjectSizeWithStroke(fabricObject), newX = (fabricObject.points[anchorIndex].x - fabricObject.pathOffset.x) / polygonBaseSize.x, newY = (fabricObject.points[anchorIndex].y - fabricObject.pathOffset.y) / polygonBaseSize.y;
fabricObject.setPositionByOrigin(absolutePoint, newX + 0.5, newY + 0.5);
return actionPerformed;
};
}
function polygonEdit() {
// 克隆自你以来你在复制什么
// 可能需要在不同时刻复制和粘贴.
// 你不希望发生变化
// 稍后再反思副本.
var poly = canvas.getObjects()[0];
canvas.setActiveObject(poly);
var lastControl = poly.points.length - 1;
poly.cornerStyle = 'circle';
poly.cornerColor = 'rgba(0,43,255,0.9)';
poly.cornerSize = 12;
poly.controls = poly.points.reduce(function (acc, point, index) {
acc['p' + index] = new fabric.Control({
positionHandler: polygonPositionHandler,
actionHandler: anchorWrapper(index > 0 ? index - 1 : lastControl, actionHandler),
actionName: 'modifyPolygon',
pointIndex: index
});
return acc;
}, {});
poly.hasBorders = false;
canvas.requestRenderAll();
}
};
rectDraw.prototype.finish = function () {
this.drawing = false;
this.rectangle.style.zIndex = '1';
var canvas = this.canvas;
this.drawType('');
if (canvas.getObjects().length > 0) {
canvas.discardActiveObject().renderAll();
this.setRatio();
return true;
}
else {
this.proportion = rectangleDefault;
return false;
}
};
rectDraw.prototype.remove = function () {
var _a = this, canvas = _a.canvas, downObject = _a.downObject;
if (downObject) {
canvas.remove(downObject.target);
}
if (canvas.getObjects().length === 0) {
this.drawType('rect');
}
};
rectDraw.prototype.setRatio = function () {
return __awaiter(this, void 0, void 0, function () {
var data, _a, clientHeight, clientWidth, arr, oCoords, field;
return __generator(this, function (_b) {
switch (_b.label) {
case 0: return [4 /*yield*/, this.canvas.getObjects()];
case 1:
data = _b.sent();
if (data.length > 0) {
_a = this.fabricDom, clientHeight = _a.clientHeight, clientWidth = _a.clientWidth;
arr = Object.keys(data[0].oCoords);
oCoords = arr[0] === 'p0' ? data[0].oCoords : data[0].points;
this.proportion = [];
for (field in oCoords) {
this.proportion.push({ x: oCoords[field].x / clientWidth, y: oCoords[field].y / clientHeight });
}
}
return [2 /*return*/];
}
});
});
};
rectDraw.prototype.getRatio = function () {
return this.proportion;
};
rectDraw.prototype.setProportion = function (shape) {
var isErr = false;
if (shape && shape instanceof Array && shape.length > 2) {
// 判断数据格式是否正确
isErr = shape.reduce(function (per, item) {
var isNan = parseFloat(item.x).toString() !== "NaN" && parseFloat(item.y).toString() !== "NaN";
if (isNan) {
if ((item.x < 0 && item.x > 1) || (item.y < 0 && item.y > 1)) {
per = false;
}
}
else {
per = false;
}
return per;
}, true);
}
this.proportion = isErr ? shape : rectangleDefault;
if (!isErr && shape !== undefined) {
console.log('错误:绘制多边形数据或格式不正确');
}
};
// 取消绘制
rectDraw.prototype.cancelRatio = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.proportion = __spreadArray([], this.initialPoint, true);
this.resetRect();
return [2 /*return*/];
});
});
};
rectDraw.prototype.destroy = function () {
if (this.canvas) {
this.canvas.dispose();
this.canvas = undefined;
}
this.proportion = [];
if (this.emitter) {
this.emitter.removeAllListeners();
this.emitter = null;
}
};
return rectDraw;
}());
export { rectDraw };
//# sourceMappingURL=draw.js.map