UNPKG

@jxstjh/jhvideo

Version:

HTML5 jhvideo base on MPEG2-TS Stream Player

492 lines 22.4 kB
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