Merge remote-tracking branch 'remotes/origin/develop' into hongbo/file-cabinet
This commit is contained in:
commit
38fb02e322
@ -51,7 +51,6 @@
|
|||||||
"prettier --parser=typescript --write"
|
"prettier --parser=typescript --write"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@changesets/cli": "^2.27.1",
|
"@changesets/cli": "^2.27.1",
|
||||||
"@commitlint/cli": "^17.1.2",
|
"@commitlint/cli": "^17.1.2",
|
||||||
|
@ -1,5 +1,22 @@
|
|||||||
# @zhst/biz
|
# @zhst/biz
|
||||||
|
|
||||||
|
## 0.16.1
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- zhst/biz: fix: 在业务层控制窗口切换状态
|
||||||
|
|
||||||
|
## 0.16.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- zhst/meta 大图圈选组件点击选不上 bug 修复,attach 遮挡底部框事件阻止修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.14.0
|
||||||
|
|
||||||
## 0.15.0
|
## 0.15.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/biz",
|
"name": "@zhst/biz",
|
||||||
"version": "0.15.0",
|
"version": "0.16.1",
|
||||||
"description": "业务库",
|
"description": "业务库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
:global {
|
:global {
|
||||||
i:hover {
|
i:hover {
|
||||||
color: #f0f0f0 !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ const Navigation: React.FC<{
|
|||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Button type="text" disabled={disabled} onClick={onClick}>
|
<Button type="text" disabled={disabled} shape='circle' onClick={onClick}>
|
||||||
<IconFont size={28} color={color} icon={prev ? 'icon-qiehuanzuo' : 'icon-qiehuanyou'} />
|
<IconFont size={28} color={color} icon={prev ? 'icon-qiehuanzuo' : 'icon-qiehuanyou'} />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,13 +53,13 @@ export const WindowToggle: React.FC<WindowToggleProps> = (props) => {
|
|||||||
<div className='body'>
|
<div className='body'>
|
||||||
{
|
{
|
||||||
dataSource?.map((item, index) => {
|
dataSource?.map((item, index) => {
|
||||||
|
|
||||||
if (size === "large" && index > 0) return
|
if (size === "large" && index > 0) return
|
||||||
return (
|
return (
|
||||||
<VideoPlayerCard
|
<VideoPlayerCard
|
||||||
key={item.windowKey}
|
key={item.windowKey}
|
||||||
selectedWindowKey={selectedWindowKey}
|
selectedWindowKey={selectedWindowKey}
|
||||||
size={size}
|
size={size}
|
||||||
handleWindowClick={handleWindowClick}
|
handleWindowClick={handleWindowClick}
|
||||||
handleCloseButtonClick={handleCloseButtonClick}
|
handleCloseButtonClick={handleCloseButtonClick}
|
||||||
{...item}
|
{...item}
|
||||||
|
@ -69,11 +69,8 @@ const demo = () => {
|
|||||||
autoSelectDisable={paintType === 'auto'}
|
autoSelectDisable={paintType === 'auto'}
|
||||||
onCropEnd={_cropData => console.log('结束绘制:', _cropData)}
|
onCropEnd={_cropData => console.log('结束绘制:', _cropData)}
|
||||||
onReset={() => console.log('重置')}
|
onReset={() => console.log('重置')}
|
||||||
onRotate={() => console.log('旋转', odModalRef.current.rotateTo(90))}
|
onRotate={() => console.log('旋转', odModalRef.current?.rotateTo?.(90))}
|
||||||
onTypeSelect={(val) => {
|
onTypeSelect={(val) => {
|
||||||
if (val === 1) {
|
|
||||||
|
|
||||||
}
|
|
||||||
setSelectedType(val)
|
setSelectedType(val)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# @zhst/utils
|
# @zhst/utils
|
||||||
|
|
||||||
|
## 0.10.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/request@0.11.0
|
||||||
|
|
||||||
## 0.10.1
|
## 0.10.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/func",
|
"name": "@zhst/func",
|
||||||
"version": "0.10.1",
|
"version": "0.10.2",
|
||||||
"description": "函数合集",
|
"description": "函数合集",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"hooks"
|
"hooks"
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# @zhst/hooks
|
# @zhst/hooks
|
||||||
|
|
||||||
|
## 0.9.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
|
||||||
## 0.9.1
|
## 0.9.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/hooks",
|
"name": "@zhst/hooks",
|
||||||
"version": "0.9.1",
|
"version": "0.9.2",
|
||||||
"description": "hooks合集",
|
"description": "hooks合集",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"hooks"
|
"hooks"
|
||||||
|
@ -1,5 +1,26 @@
|
|||||||
# @zhst/material
|
# @zhst/material
|
||||||
|
|
||||||
|
## 0.10.4
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/biz@0.16.1
|
||||||
|
|
||||||
|
## 0.10.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.14.0
|
||||||
|
- @zhst/biz@0.16.0
|
||||||
|
|
||||||
|
## 0.10.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- material 修改找不到包的问题
|
||||||
|
|
||||||
## 0.10.1
|
## 0.10.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/material",
|
"name": "@zhst/material",
|
||||||
"version": "0.10.1",
|
"version": "0.10.4",
|
||||||
"description": "物料库",
|
"description": "物料库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"business",
|
"business",
|
||||||
|
@ -1,5 +1,29 @@
|
|||||||
# @zhst/utils
|
# @zhst/utils
|
||||||
|
|
||||||
|
## 0.15.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 视频添加 OD 框,查看大图首次点击修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.15.0
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
- @zhst/hooks@0.9.2
|
||||||
|
|
||||||
|
## 0.14.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- zhst/meta 大图圈选组件点击选不上 bug 修复,attach 遮挡底部框事件阻止修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies
|
||||||
|
- @zhst/meta@0.14.0
|
||||||
|
|
||||||
## 0.13.0
|
## 0.13.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
@ -17,8 +17,7 @@ import React, { useEffect, useState, useRef, useImperativeHandle } from 'react';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { get, pick, isNull, generateImg, dataURLToBlob, getTransforms, addEventListenerWrapper, getFileByRect } from '@zhst/func';
|
import { get, pick, isNull, generateImg, dataURLToBlob, getTransforms, addEventListenerWrapper, getFileByRect } from '@zhst/func';
|
||||||
import Align from 'rc-align';
|
import Align from 'rc-align';
|
||||||
import { Button, Empty } from '..';
|
import { Empty, AttachImage } from '..';
|
||||||
import { IconFont as Icon } from '@zhst/icon';
|
|
||||||
import { Cropper, Viewer, EVENT_VIEWER_TRANSFORM_CHANGE, EVENT_VIEWER_READY, EVENT_CROP_START, EVENT_CROP_END } from "../ImageEditor";
|
import { Cropper, Viewer, EVENT_VIEWER_TRANSFORM_CHANGE, EVENT_VIEWER_READY, EVENT_CROP_START, EVENT_CROP_END } from "../ImageEditor";
|
||||||
import BtnGroup from "./components/BtnGroup";
|
import BtnGroup from "./components/BtnGroup";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
@ -480,16 +479,6 @@ export var BigImagePreview = /*#__PURE__*/React.forwardRef(function (props, ref)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================= attact img =========================
|
|
||||||
var _useState17 = useState(0),
|
|
||||||
_useState18 = _slicedToArray(_useState17, 2),
|
|
||||||
selectAttachImgIndex = _useState18[0],
|
|
||||||
setSelectAttachImgIndex = _useState18[1];
|
|
||||||
var _useState19 = useState(false),
|
|
||||||
_useState20 = _slicedToArray(_useState19, 2),
|
|
||||||
isZoomin = _useState20[0],
|
|
||||||
setIsZoomin = _useState20[1];
|
|
||||||
|
|
||||||
// ============================== Ref ===============================
|
// ============================== Ref ===============================
|
||||||
useImperativeHandle(ref, function () {
|
useImperativeHandle(ref, function () {
|
||||||
return {
|
return {
|
||||||
@ -544,46 +533,10 @@ export var BigImagePreview = /*#__PURE__*/React.forwardRef(function (props, ref)
|
|||||||
setShowCrop: setShowCrop,
|
setShowCrop: setShowCrop,
|
||||||
cropType: cropType,
|
cropType: cropType,
|
||||||
selectAlgorithmVersion: selectAlgorithmVersion
|
selectAlgorithmVersion: selectAlgorithmVersion
|
||||||
}))), (attachImg === null || attachImg === void 0 ? void 0 : attachImg.length) && !showCrop && /*#__PURE__*/React.createElement("div", {
|
}))), (attachImg === null || attachImg === void 0 ? void 0 : attachImg.length) && !showCrop && /*#__PURE__*/React.createElement(AttachImage, {
|
||||||
className: classNames("".concat(componentName, "-attach"), isZoomin && "".concat(componentName, "-attach--zoomin"), "".concat(componentName, "-attach--fixed"), isZoomin && "".concat(componentName, "-attach--zoomin--fixed"))
|
showAttachImgLabel: showAttachImgLabel,
|
||||||
}, /*#__PURE__*/React.createElement("div", {
|
data: attachImg
|
||||||
className: classNames("".concat(componentName, "-attach__tab"))
|
}), (showScore || score) && /*#__PURE__*/React.createElement("div", {
|
||||||
}, showAttachImgLabel ? attachImg === null || attachImg === void 0 ? void 0 : attachImg.map(function (_ref6, index) {
|
|
||||||
var label = _ref6.label;
|
|
||||||
return /*#__PURE__*/React.createElement("div", {
|
|
||||||
key: index,
|
|
||||||
className: classNames("".concat(componentName, "-attach__tab-item"), selectAttachImgIndex === index && "".concat(componentName, "-attach__tab-item--select")),
|
|
||||||
onMouseEnter: function onMouseEnter() {
|
|
||||||
setSelectAttachImgIndex(index);
|
|
||||||
}
|
|
||||||
}, label);
|
|
||||||
}) : null), /*#__PURE__*/React.createElement("div", {
|
|
||||||
className: classNames("".concat(componentName, "-attach__scale"))
|
|
||||||
}, /*#__PURE__*/React.createElement(Button, {
|
|
||||||
type: "text"
|
|
||||||
//绝对定位下onClick事件失效采用onMouseDown
|
|
||||||
,
|
|
||||||
onMouseDown: function onMouseDown(e) {
|
|
||||||
//如果是左键执行
|
|
||||||
if (e.button == 0) {
|
|
||||||
setIsZoomin(function (pre) {
|
|
||||||
return !pre;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
}, /*#__PURE__*/React.createElement(Icon, {
|
|
||||||
styles: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
icon: isZoomin ? 'icon-cancle_fullscreen' : 'icon-fullscreen'
|
|
||||||
}))), /*#__PURE__*/React.createElement("img", {
|
|
||||||
draggable: "false",
|
|
||||||
className: classNames("".concat(componentName, "-attach__img"), "".concat(componentName, "-attach__img--fixed")),
|
|
||||||
src: get(attachImg, "".concat(selectAttachImgIndex, ".url"), '')
|
|
||||||
})), (showScore || score) && /*#__PURE__*/React.createElement("div", {
|
|
||||||
style: {
|
style: {
|
||||||
bottom: 20
|
bottom: 20
|
||||||
},
|
},
|
||||||
|
@ -30,31 +30,32 @@ export default {
|
|||||||
_this$eventHandleList = this.eventHandleList,
|
_this$eventHandleList = this.eventHandleList,
|
||||||
eventHandleList = _this$eventHandleList === void 0 ? [] : _this$eventHandleList,
|
eventHandleList = _this$eventHandleList === void 0 ? [] : _this$eventHandleList,
|
||||||
options = this.options;
|
options = this.options;
|
||||||
//图片事件
|
// 鼠标滚轮事件
|
||||||
var scaleAble = get(options, 'scaleAble', true);
|
var scaleAble = get(options, 'scaleAble', true);
|
||||||
if (scaleAble) {
|
if (scaleAble) {
|
||||||
var handleWhele = addEventListenerWrapper(canvas, EVENT_WHEEL, this.onWheel.bind(this));
|
var handleWheel = addEventListenerWrapper(canvas, EVENT_WHEEL, this.onWheel.bind(this));
|
||||||
eventHandleList.push(handleWhele);
|
eventHandleList.push(handleWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 鼠标 - 拖拽事件
|
||||||
var dragAble = get(options, 'dragAble', true);
|
var dragAble = get(options, 'dragAble', true);
|
||||||
if (dragAble) {
|
if (dragAble) {
|
||||||
var handleDragStart = addEventListenerWrapper(canvas, EVENT_POINTER_DOWN, this.onDragStart.bind(this));
|
var handleDragStart = addEventListenerWrapper(canvas, EVENT_POINTER_DOWN, this.onDragStart.bind(this));
|
||||||
eventHandleList.push(addEventListenerWrapper);
|
eventHandleList.push(handleDragStart);
|
||||||
var handleDragMove = addEventListenerWrapper(element.ownerDocument, EVENT_POINTER_MOVE, this.onDragMove.bind(this));
|
var handleDragMove = addEventListenerWrapper(element.ownerDocument, EVENT_POINTER_MOVE, this.onDragMove.bind(this));
|
||||||
eventHandleList.push(handleDragMove);
|
eventHandleList.push(handleDragMove);
|
||||||
EVENT_POINTER_UP.trim().split(REGEXP_SPACES).forEach(function (eventName) {
|
EVENT_POINTER_UP.trim().split(REGEXP_SPACES).forEach(function (_eventName) {
|
||||||
var handleDragEnd = addEventListenerWrapper(element.ownerDocument, eventName, _this.onDragEnd.bind(_this));
|
var handleDragEnd = addEventListenerWrapper(element.ownerDocument, _eventName, _this.onDragEnd.bind(_this));
|
||||||
eventHandleList.push(handleDragEnd);
|
eventHandleList.push(handleDragEnd);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//rect事件
|
// 鼠标 - 点击事件
|
||||||
var handleClick = addEventListenerWrapper(canvas, EVENT_CLICK, this.onClick.bind(this));
|
var selectAble = get(options, 'selectAble', true);
|
||||||
eventHandleList.push(handleClick);
|
if (selectAble) {
|
||||||
// const handleLeveal = addEventListenerWrapper(canvas, EVENT_LEAVEL, this.onLeavel.bind(this));
|
var handleClick = addEventListenerWrapper(canvas, EVENT_CLICK, this.onClick.bind(this));
|
||||||
// eventHandleList.push(handleLeveal);
|
eventHandleList.push(handleClick);
|
||||||
// const handleEnter = addEventListenerWrapper(canvas, EVENT_ENTER, this.onEnter.bind(this));
|
}
|
||||||
// eventHandleList.push(handleEnter);
|
|
||||||
},
|
},
|
||||||
unbind: function unbind() {
|
unbind: function unbind() {
|
||||||
var eventHandleList = this.eventHandleList;
|
var eventHandleList = this.eventHandleList;
|
||||||
@ -67,7 +68,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* 图片事件 */onWheel: function onWheel(event, cropBox) {
|
/* 鼠标滚轮事件 */onWheel: function onWheel(event, cropBox) {
|
||||||
var _this2 = this;
|
var _this2 = this;
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -97,6 +98,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}, cropBox);
|
}, cropBox);
|
||||||
},
|
},
|
||||||
|
// 鼠标拖拽 - 开始拖拽
|
||||||
onDragStart: function onDragStart(event) {
|
onDragStart: function onDragStart(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
// This line is required for preventing page zooming in iOS browsers
|
// This line is required for preventing page zooming in iOS browsers
|
||||||
@ -119,6 +121,7 @@ export default {
|
|||||||
this.action = ACTION_DRAG;
|
this.action = ACTION_DRAG;
|
||||||
addClass(this.canvas, CLASS_MOVE);
|
addClass(this.canvas, CLASS_MOVE);
|
||||||
},
|
},
|
||||||
|
// 鼠标拖拽 - 拖拽中
|
||||||
onDragMove: function onDragMove(event) {
|
onDragMove: function onDragMove(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@ -147,6 +150,7 @@ export default {
|
|||||||
this.pointer.startX = this.pointer.endX;
|
this.pointer.startX = this.pointer.endX;
|
||||||
this.pointer.startY = this.pointer.endY;
|
this.pointer.startY = this.pointer.endY;
|
||||||
},
|
},
|
||||||
|
// 鼠标拖拽 - 停止拖拽
|
||||||
onDragEnd: function onDragEnd(event) {
|
onDragEnd: function onDragEnd(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
var action = this.action;
|
var action = this.action;
|
||||||
@ -158,14 +162,7 @@ export default {
|
|||||||
this.point = null;
|
this.point = null;
|
||||||
removeClass(this.canvas, CLASS_MOVE);
|
removeClass(this.canvas, CLASS_MOVE);
|
||||||
},
|
},
|
||||||
/* rect事件 */
|
// 鼠标点击
|
||||||
// onLeavel(event) {
|
|
||||||
// const pointerCenter = this.windowToCanvasAxis(event);
|
|
||||||
// this.highlightShape(pointerCenter);
|
|
||||||
// },
|
|
||||||
// onEnter(event) {
|
|
||||||
// this.highlightShape(null);
|
|
||||||
// },
|
|
||||||
onClick: function onClick(event) {
|
onClick: function onClick(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
var pointerCenter = this.windowToCanvasAxis(event);
|
var pointerCenter = this.windowToCanvasAxis(event);
|
||||||
|
@ -13,7 +13,12 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|||||||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
||||||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
||||||
//@ts-nocheck
|
//@ts-nocheck
|
||||||
|
import * as turf from '@turf/turf';
|
||||||
import { AXIS_TYPE_ORIGIN, AXIS_TYPE_CANVAS, AXIS_TYPE_IMAGE } from "./constants";
|
import { AXIS_TYPE_ORIGIN, AXIS_TYPE_CANVAS, AXIS_TYPE_IMAGE } from "./constants";
|
||||||
|
export function rectToPolygon(axisRect) {
|
||||||
|
var polygon = turf.polygon([[[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)], [setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y, -2)], [setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y2, -2)], [setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y2, -2)], [setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)]]]);
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
//设置数据的精度
|
//设置数据的精度
|
||||||
//accuracy 表示精度 以原点为中心向左为正,向右为负,
|
//accuracy 表示精度 以原点为中心向左为正,向右为负,
|
||||||
@ -42,17 +47,14 @@ export default {
|
|||||||
targetTransform: {
|
targetTransform: {
|
||||||
translateX: 0,
|
translateX: 0,
|
||||||
translateY: 0,
|
translateY: 0,
|
||||||
scale: 0,
|
scale: 1,
|
||||||
rotate: 0
|
rotate: 0
|
||||||
// rotate: 90,
|
// rotate: 90,
|
||||||
},
|
},
|
||||||
windowToCanvasAxis: function windowToCanvasAxis(event) {
|
windowToCanvasAxis: function windowToCanvasAxis(event) {
|
||||||
var _this$canvas$getBound = this.canvas.getBoundingClientRect(),
|
|
||||||
x = _this$canvas$getBound.x,
|
|
||||||
y = _this$canvas$getBound.y;
|
|
||||||
return {
|
return {
|
||||||
x: event.pageX - x,
|
x: event.offsetX,
|
||||||
y: event.pageY - y,
|
y: event.offsetY,
|
||||||
__AXIS_TYPE__: AXIS_TYPE_CANVAS
|
__AXIS_TYPE__: AXIS_TYPE_CANVAS
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -76,7 +78,8 @@ export default {
|
|||||||
var targetTransform = this.targetTransform;
|
var targetTransform = this.targetTransform;
|
||||||
var translateX = targetTransform.translateX,
|
var translateX = targetTransform.translateX,
|
||||||
translateY = targetTransform.translateY,
|
translateY = targetTransform.translateY,
|
||||||
scale = targetTransform.scale;
|
_targetTransform$scal = targetTransform.scale,
|
||||||
|
scale = _targetTransform$scal === void 0 ? 1 : _targetTransform$scal;
|
||||||
var axis = _objectSpread(_objectSpread({
|
var axis = _objectSpread(_objectSpread({
|
||||||
x: translateX + x * scale,
|
x: translateX + x * scale,
|
||||||
y: translateY + y * scale
|
y: translateY + y * scale
|
||||||
|
@ -75,7 +75,14 @@ var Viewer = (_dec = Mixin(Render, Event, Shape, Helper), _dec(_class = /*#__PUR
|
|||||||
}, {
|
}, {
|
||||||
key: "build",
|
key: "build",
|
||||||
value: function build() {
|
value: function build() {
|
||||||
|
var _this$options = this.options,
|
||||||
|
_this$options$width = _this$options.width,
|
||||||
|
width = _this$options$width === void 0 ? 300 : _this$options$width,
|
||||||
|
_this$options$height = _this$options.height,
|
||||||
|
height = _this$options$height === void 0 ? 150 : _this$options$height;
|
||||||
var canvas = document.createElement('canvas');
|
var canvas = document.createElement('canvas');
|
||||||
|
canvas.width = width || canvas.width;
|
||||||
|
canvas.height = height || canvas.height;
|
||||||
addClass(canvas, CLASS_CANVAS);
|
addClass(canvas, CLASS_CANVAS);
|
||||||
this.element.appendChild(canvas);
|
this.element.appendChild(canvas);
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
|
@ -65,7 +65,6 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
initCanvas: function initCanvas() {
|
initCanvas: function initCanvas() {
|
||||||
if (!this.image) return;
|
|
||||||
//通过样式设置 不依赖父元素的prosition
|
//通过样式设置 不依赖父元素的prosition
|
||||||
var element = this.element,
|
var element = this.element,
|
||||||
canvas = this.canvas,
|
canvas = this.canvas,
|
||||||
@ -83,7 +82,7 @@ export default {
|
|||||||
var fitTransform = this.calcFitScreen();
|
var fitTransform = this.calcFitScreen();
|
||||||
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
|
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
|
||||||
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
|
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
|
||||||
//产品需求:fitscale 是minscale
|
//产品需求:fitscale 是 minscale
|
||||||
var _options$fitScaleAsMi = options.fitScaleAsMinScale,
|
var _options$fitScaleAsMi = options.fitScaleAsMinScale,
|
||||||
fitScaleAsMinScale = _options$fitScaleAsMi === void 0 ? false : _options$fitScaleAsMi;
|
fitScaleAsMinScale = _options$fitScaleAsMi === void 0 ? false : _options$fitScaleAsMi;
|
||||||
if (fitScaleAsMinScale) {
|
if (fitScaleAsMinScale) {
|
||||||
@ -106,8 +105,9 @@ export default {
|
|||||||
};
|
};
|
||||||
loop();
|
loop();
|
||||||
},
|
},
|
||||||
|
// 绘制画布
|
||||||
renderCanvas: function renderCanvas(_ctx) {
|
renderCanvas: function renderCanvas(_ctx) {
|
||||||
if (!this.image || !this.canvas) return;
|
if (!this.canvas) return;
|
||||||
var containerData = this.containerData,
|
var containerData = this.containerData,
|
||||||
canvas = this.canvas,
|
canvas = this.canvas,
|
||||||
targetTransform = this.targetTransform,
|
targetTransform = this.targetTransform,
|
||||||
@ -128,14 +128,14 @@ export default {
|
|||||||
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
||||||
// ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
// ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
||||||
//旋转
|
//旋转
|
||||||
var centerX = this.image.width / 2;
|
var centerX = this.image ? this.image.width / 2 : canvas.width;
|
||||||
var centerY = this.image.height / 2;
|
var centerY = this.image ? this.image.height / 2 : canvas.height;
|
||||||
ctx.translate(centerX, centerY);
|
ctx.translate(centerX, centerY);
|
||||||
ctx.rotate(rotate / 180 * Math.PI);
|
ctx.rotate(rotate / 180 * Math.PI);
|
||||||
ctx.translate(-centerX, -centerY);
|
ctx.translate(-centerX, -centerY);
|
||||||
|
|
||||||
//图片
|
//图片
|
||||||
ctx.drawImage(this.image, 0, 0);
|
this.image && ctx.drawImage(this.image, 0, 0);
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
//画图形
|
//画图形
|
||||||
ctx.save();
|
ctx.save();
|
||||||
|
@ -14,13 +14,9 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|||||||
import { isNil, isArray, isFunction } from '@zhst/func';
|
import { isNil, isArray, isFunction } from '@zhst/func';
|
||||||
import * as turf from '@turf/turf';
|
import * as turf from '@turf/turf';
|
||||||
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
||||||
import { setNumberAccuracy } from "./helper";
|
import { rectToPolygon } from "./helper";
|
||||||
import { SHAPE_TYPE_RECT, SHAPE_TYPE_CIRCLE, EVENT_SHAPE_SELECT } from "./constants";
|
import { SHAPE_TYPE_RECT, SHAPE_TYPE_CIRCLE, EVENT_SHAPE_SELECT } from "./constants";
|
||||||
import { dispatchEvent } from "../utils";
|
import { dispatchEvent } from "../utils";
|
||||||
function rectToPolygon(axisRect) {
|
|
||||||
var polygon = turf.polygon([[[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)], [setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y, -2)], [setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y2, -2)], [setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y2, -2)], [setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)]]]);
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
export default {
|
export default {
|
||||||
//store
|
//store
|
||||||
shapeList: [],
|
shapeList: [],
|
||||||
@ -47,20 +43,20 @@ export default {
|
|||||||
this.changeZoonAble(true);
|
this.changeZoonAble(true);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//method
|
//method:添加矩形
|
||||||
addShape: function addShape(shap) {
|
addShape: function addShape(shape) {
|
||||||
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : SHAPE_TYPE_RECT;
|
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : SHAPE_TYPE_RECT;
|
||||||
this.color = shap.color ? shap.color : '';
|
this.color = shape.color ? shape.color : '';
|
||||||
if (isNil(shap) || this.disableAdd) return;
|
if (isNil(shape) || this.disableAdd) return;
|
||||||
var _this$shapeList = this.shapeList,
|
var _this$shapeList = this.shapeList,
|
||||||
preShapeList = _this$shapeList === void 0 ? [] : _this$shapeList;
|
preShapeList = _this$shapeList === void 0 ? [] : _this$shapeList;
|
||||||
var shapList = isArray(shap) ? shap : [shap];
|
var _shapeList = isArray(shape) ? shape : [shape];
|
||||||
shapList = shapList.map(function (v) {
|
_shapeList = _shapeList.map(function (v) {
|
||||||
return _objectSpread(_objectSpread({}, v), {}, {
|
return _objectSpread(_objectSpread({}, v), {}, {
|
||||||
__SHAPE_TYPE__: type
|
__SHAPE_TYPE__: type
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.shapeList = [].concat(_toConsumableArray(preShapeList), _toConsumableArray(shapList));
|
this.shapeList = [].concat(_toConsumableArray(preShapeList), _toConsumableArray(_shapeList));
|
||||||
},
|
},
|
||||||
//
|
//
|
||||||
setSelectShapId: function setSelectShapId(id) {
|
setSelectShapId: function setSelectShapId(id) {
|
||||||
@ -214,9 +210,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 绘制矩形
|
||||||
renderRect: function renderRect(ctx, shape, type) {
|
renderRect: function renderRect(ctx, shape, type) {
|
||||||
//算rect
|
//算rect
|
||||||
var axisRect = this.imgRectAxisToCanvasAxisRect(shape);
|
var axisRect = this.imgRectAxisToCanvasAxisRect(_objectSpread(_objectSpread({}, shape), {}, {
|
||||||
|
image: ctx.canvas
|
||||||
|
}));
|
||||||
var rect = {
|
var rect = {
|
||||||
x: axisRect.x2 > axisRect.x ? axisRect.x : axisRect.x2,
|
x: axisRect.x2 > axisRect.x ? axisRect.x : axisRect.x2,
|
||||||
y: axisRect.y2 > axisRect.y ? axisRect.y : axisRect.y2,
|
y: axisRect.y2 > axisRect.y ? axisRect.y : axisRect.y2,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||||
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
||||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||||
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||||
@ -18,15 +19,14 @@ import { noop, get, addEventListenerWrapper, dataURLToBlob, nextTick, toRealNumb
|
|||||||
import Align from 'rc-align';
|
import Align from 'rc-align';
|
||||||
import { useLatest, useUpdateEffect, useFullscreen, useUnmount } from '@zhst/hooks';
|
import { useLatest, useUpdateEffect, useFullscreen, useUnmount } from '@zhst/hooks';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import download from 'downloadjs';
|
import { message } from '..';
|
||||||
import { Button, message } from '..';
|
|
||||||
import { IconFont } from '@zhst/icon';
|
import { IconFont } from '@zhst/icon';
|
||||||
import { Cropper, EVENT_CROP_START, EVENT_CROP_END } from "../ImageEditor";
|
import { Cropper, EVENT_CROP_START, EVENT_CROP_END, Viewer } from "../ImageEditor";
|
||||||
import FlvPlayer, { FLV_EVENT } from "./components/FlvPlayer";
|
import FlvPlayer, { FLV_EVENT } from "./components/FlvPlayer";
|
||||||
import Range from "./components/Progress";
|
import Range from "./components/Progress";
|
||||||
import Loading from "./components/Loading";
|
import Loading from "./components/Loading";
|
||||||
import { CROP_TYPE } from "../utils/constants";
|
import { CROP_TYPE } from "../utils/constants";
|
||||||
import { getShowStatus } from "./videoPlayerHelper";
|
import { downloadFrame, getShowStatus } from "./videoPlayerHelper";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
var componentName = "zhst-image__video-view";
|
var componentName = "zhst-image__video-view";
|
||||||
var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
||||||
@ -42,6 +42,16 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
adjustY: true
|
adjustY: true
|
||||||
}
|
}
|
||||||
} : _props$screenshotButt,
|
} : _props$screenshotButt,
|
||||||
|
_props$autoPlay = props.autoPlay,
|
||||||
|
autoPlay = _props$autoPlay === void 0 ? false : _props$autoPlay,
|
||||||
|
odList = props.odList,
|
||||||
|
showOD = props.showOD,
|
||||||
|
_props$width = props.width,
|
||||||
|
width = _props$width === void 0 ? '100%' : _props$width,
|
||||||
|
_props$height = props.height,
|
||||||
|
height = _props$height === void 0 ? '532px' : _props$height,
|
||||||
|
_props$backgroundColo = props.backgroundColor,
|
||||||
|
backgroundColor = _props$backgroundColo === void 0 ? '#333' : _props$backgroundColo,
|
||||||
_props$screenshotButt2 = props.screenshotButtonRender,
|
_props$screenshotButt2 = props.screenshotButtonRender,
|
||||||
screenshotButtonRender = _props$screenshotButt2 === void 0 ? function () {
|
screenshotButtonRender = _props$screenshotButt2 === void 0 ? function () {
|
||||||
return /*#__PURE__*/React.createElement("div", {
|
return /*#__PURE__*/React.createElement("div", {
|
||||||
@ -53,7 +63,8 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
}, "\u56DE\u8C03DOM");
|
}, "\u56DE\u8C03DOM");
|
||||||
} : _props$screenshotButt2,
|
} : _props$screenshotButt2,
|
||||||
onCropChange = props.onCropChange,
|
onCropChange = props.onCropChange,
|
||||||
defaultNormalizationRect = props.defautlNormalizationRect;
|
defaultNormalizationRect = props.defautlNormalizationRect,
|
||||||
|
playerProps = props.playerProps;
|
||||||
// ========================== 播放 =========================
|
// ========================== 播放 =========================
|
||||||
//实例参数
|
//实例参数
|
||||||
var containerRef = useRef(null); //容器ref
|
var containerRef = useRef(null); //容器ref
|
||||||
@ -257,6 +268,8 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 重新加载
|
||||||
var _reload = /*#__PURE__*/function () {
|
var _reload = /*#__PURE__*/function () {
|
||||||
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
||||||
var oldTime;
|
var oldTime;
|
||||||
@ -309,6 +322,8 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
return _ref.apply(this, arguments);
|
return _ref.apply(this, arguments);
|
||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
// 进度条操作
|
||||||
var seek = function seek(v) {
|
var seek = function seek(v) {
|
||||||
if (videoInsRef.current && isVideoLoadFinished) {
|
if (videoInsRef.current && isVideoLoadFinished) {
|
||||||
setPlayTime(parseFloat(v));
|
setPlayTime(parseFloat(v));
|
||||||
@ -317,6 +332,7 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
message.warning('待视频加载完,才可操作进度条');
|
message.warning('待视频加载完,才可操作进度条');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========================== 视频opt bar =========================
|
// ========================== 视频opt bar =========================
|
||||||
var _useFullscreen = useFullscreen(containerRef, {
|
var _useFullscreen = useFullscreen(containerRef, {
|
||||||
pageFullscreen: true
|
pageFullscreen: true
|
||||||
@ -354,17 +370,15 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
_useState22 = _slicedToArray(_useState21, 2),
|
_useState22 = _slicedToArray(_useState21, 2),
|
||||||
cropRect = _useState22[0],
|
cropRect = _useState22[0],
|
||||||
setCropRect = _useState22[1];
|
setCropRect = _useState22[1];
|
||||||
useEffect(function () {
|
|
||||||
var _videoInsRef$current4, _videoInsRef$current5;
|
// 监听showCrop, isReady - 是否可编辑、视频播放组件是否挂载
|
||||||
showCrop ? videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current4 = videoInsRef.current) === null || _videoInsRef$current4 === void 0 ? void 0 : _videoInsRef$current4.pause() : videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current5 = videoInsRef.current) === null || _videoInsRef$current5 === void 0 ? void 0 : _videoInsRef$current5.play();
|
|
||||||
}, [showCrop]);
|
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
var handlerCropStart;
|
var handlerCropStart;
|
||||||
var handlerCropEnd;
|
var handlerCropEnd;
|
||||||
setCropRect(null);
|
setCropRect(null);
|
||||||
if (!isReady) return;
|
if (!isReady) return;
|
||||||
if (showCrop) {
|
if (showCrop) {
|
||||||
var _canvas$parentNode;
|
var _canvas$parentNode, _videoInsRef$current4;
|
||||||
handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, function () {
|
handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, function () {
|
||||||
setCropRect(null);
|
setCropRect(null);
|
||||||
});
|
});
|
||||||
@ -412,18 +426,41 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
isFirstFlagRef.current = false;
|
isFirstFlagRef.current = false;
|
||||||
|
|
||||||
|
// 初始化圈选工具
|
||||||
cropInsRef.current = new Cropper(corpContainerRef.current, {
|
cropInsRef.current = new Cropper(corpContainerRef.current, {
|
||||||
showMask: true,
|
showMask: true,
|
||||||
cropBoxLimited: cropBoxLimited,
|
cropBoxLimited: cropBoxLimited,
|
||||||
|
editAble: false,
|
||||||
img: imageData,
|
img: imageData,
|
||||||
initialCropBoxData: initialCropBoxData
|
initialCropBoxData: initialCropBoxData
|
||||||
});
|
});
|
||||||
|
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current4 = videoInsRef.current) === null || _videoInsRef$current4 === void 0 || _videoInsRef$current4.pause();
|
||||||
|
} else {
|
||||||
|
var _videoInsRef$current5;
|
||||||
|
var _element = videoInsRef.current._mediaElement || {};
|
||||||
|
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current5 = videoInsRef.current) === null || _videoInsRef$current5 === void 0 || _videoInsRef$current5.play();
|
||||||
|
// 挂载图片选择
|
||||||
|
cropInsRef.current = new Viewer(corpContainerRef.current, {
|
||||||
|
scaleAble: false,
|
||||||
|
selectAble: false,
|
||||||
|
dragAble: false,
|
||||||
|
width: _element.clientWidth,
|
||||||
|
height: _element.clientHeight,
|
||||||
|
backgroundColor: 'transparent'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 判定是否存在od框
|
||||||
|
showOD && (odList === null || odList === void 0 ? void 0 : odList.forEach(function (_od) {
|
||||||
|
var _cropInsRef$current;
|
||||||
|
cropInsRef === null || cropInsRef === void 0 || (_cropInsRef$current = cropInsRef.current) === null || _cropInsRef$current === void 0 || _cropInsRef$current.addShape(_od);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
return function () {
|
return function () {
|
||||||
var _handlerCropStart, _handlerCropEnd, _cropInsRef$current, _cropInsRef$current$d;
|
var _handlerCropStart, _handlerCropEnd, _cropInsRef$current2, _cropInsRef$current2$;
|
||||||
(_handlerCropStart = handlerCropStart) === null || _handlerCropStart === void 0 || _handlerCropStart.remove();
|
(_handlerCropStart = handlerCropStart) === null || _handlerCropStart === void 0 || _handlerCropStart.remove();
|
||||||
(_handlerCropEnd = handlerCropEnd) === null || _handlerCropEnd === void 0 || _handlerCropEnd.remove();
|
(_handlerCropEnd = handlerCropEnd) === null || _handlerCropEnd === void 0 || _handlerCropEnd.remove();
|
||||||
cropInsRef === null || cropInsRef === void 0 || (_cropInsRef$current = cropInsRef.current) === null || _cropInsRef$current === void 0 || (_cropInsRef$current$d = _cropInsRef$current.destroy) === null || _cropInsRef$current$d === void 0 || _cropInsRef$current$d.call(_cropInsRef$current);
|
cropInsRef === null || cropInsRef === void 0 || (_cropInsRef$current2 = cropInsRef.current) === null || _cropInsRef$current2 === void 0 || (_cropInsRef$current2$ = _cropInsRef$current2.destroy) === null || _cropInsRef$current2$ === void 0 || _cropInsRef$current2$.call(_cropInsRef$current2);
|
||||||
cropInsRef.current = null;
|
cropInsRef.current = null;
|
||||||
};
|
};
|
||||||
}, [showCrop, isReady]);
|
}, [showCrop, isReady]);
|
||||||
@ -502,7 +539,7 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
};
|
};
|
||||||
}();
|
}();
|
||||||
|
|
||||||
//回调
|
// 监听showCrop、cropRect - 监听是否可编辑、绘制的矩形
|
||||||
useEffect(function () {
|
useEffect(function () {
|
||||||
//计算归一化crop rect
|
//计算归一化crop rect
|
||||||
var normalizationRect = null;
|
var normalizationRect = null;
|
||||||
@ -528,41 +565,11 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
}, [showCrop, cropRect]);
|
}, [showCrop, cropRect]);
|
||||||
|
|
||||||
// ========================== 截帧 =========================
|
// ========================== 截帧 =========================
|
||||||
var downloadVideoframe = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
|
var downloadVideoFrame = useCallback(function (opt) {
|
||||||
var _videoInsRef$current6, _videoInsRef$current7, video, canvas, ctx, base64;
|
var _videoInsRef$current6, _videoInsRef$current7;
|
||||||
return _regeneratorRuntime().wrap(function _callee4$(_context4) {
|
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current6 = videoInsRef.current) === null || _videoInsRef$current6 === void 0 || (_videoInsRef$current7 = _videoInsRef$current6.pause) === null || _videoInsRef$current7 === void 0 || _videoInsRef$current7.call(_videoInsRef$current6);
|
||||||
while (1) switch (_context4.prev = _context4.next) {
|
downloadFrame(videoRef.current, opt);
|
||||||
case 0:
|
}, []);
|
||||||
try {
|
|
||||||
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current6 = videoInsRef.current) === null || _videoInsRef$current6 === void 0 || (_videoInsRef$current7 = _videoInsRef$current6.pause) === null || _videoInsRef$current7 === void 0 || _videoInsRef$current7.call(_videoInsRef$current6);
|
|
||||||
video = videoRef.current;
|
|
||||||
canvas = document.createElement('canvas');
|
|
||||||
ctx = canvas.getContext('2d');
|
|
||||||
//当视频处于还未加载出来时,截屏为黑色图片
|
|
||||||
if (video.readyState === 0) {
|
|
||||||
ctx === null || ctx === void 0 || ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
canvas.width = video.offsetWidth;
|
|
||||||
canvas.height = video.offsetHeight;
|
|
||||||
// @ts-ignore
|
|
||||||
ctx.fillStyle = 'black';
|
|
||||||
ctx === null || ctx === void 0 || ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
base64 = canvas.toDataURL();
|
|
||||||
} else {
|
|
||||||
canvas.width = video.videoWidth;
|
|
||||||
canvas.height = video.videoHeight;
|
|
||||||
ctx === null || ctx === void 0 || ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
||||||
base64 = canvas.toDataURL('image/png');
|
|
||||||
}
|
|
||||||
download(base64);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
case "end":
|
|
||||||
return _context4.stop();
|
|
||||||
}
|
|
||||||
}, _callee4);
|
|
||||||
})), []);
|
|
||||||
|
|
||||||
// ============================== 暴露出去的方法 ===============================
|
// ============================== 暴露出去的方法 ===============================
|
||||||
var latestIsReady = useLatest(isReady);
|
var latestIsReady = useLatest(isReady);
|
||||||
@ -573,17 +580,31 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
setShowCrop: function setShowCrop(dispatch) {
|
setShowCrop: function setShowCrop(dispatch) {
|
||||||
var isReady = latestIsReady.current;
|
var isReady = latestIsReady.current;
|
||||||
if (!isReady) return;
|
if (!isReady) return;
|
||||||
_setShowCrop(dispatch);
|
_setShowCrop === null || _setShowCrop === void 0 || _setShowCrop(dispatch);
|
||||||
},
|
},
|
||||||
downloadVideoframe: downloadVideoframe
|
downloadVideoFrame: downloadVideoFrame,
|
||||||
|
pause: function pause() {
|
||||||
|
var _videoInsRef$current8, _videoInsRef$current9;
|
||||||
|
(_videoInsRef$current8 = videoInsRef.current) === null || _videoInsRef$current8 === void 0 || (_videoInsRef$current9 = _videoInsRef$current8.pause) === null || _videoInsRef$current9 === void 0 || _videoInsRef$current9.call(_videoInsRef$current8);
|
||||||
|
},
|
||||||
|
play: function play() {
|
||||||
|
var _videoInsRef$current10, _videoInsRef$current11;
|
||||||
|
(_videoInsRef$current10 = videoInsRef.current) === null || _videoInsRef$current10 === void 0 || (_videoInsRef$current11 = _videoInsRef$current10.play) === null || _videoInsRef$current11 === void 0 || _videoInsRef$current11.call(_videoInsRef$current10);
|
||||||
|
},
|
||||||
|
reload: _reload
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return /*#__PURE__*/React.createElement("div", {
|
return /*#__PURE__*/React.createElement("div", {
|
||||||
className: classNames("".concat(componentName)),
|
className: classNames("".concat(componentName)),
|
||||||
ref: containerRef
|
ref: containerRef,
|
||||||
}, url && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FlvPlayer, {
|
style: {
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
backgroundColor: backgroundColor
|
||||||
|
}
|
||||||
|
}, url && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FlvPlayer, _extends({
|
||||||
playId: playSeq,
|
playId: playSeq,
|
||||||
autoPlay: true,
|
autoPlay: autoPlay,
|
||||||
className: classNames("".concat(componentName, "-flv")),
|
className: classNames("".concat(componentName, "-flv")),
|
||||||
type: url.startsWith('http') ? 'mp4' : 'flv',
|
type: url.startsWith('http') ? 'mp4' : 'flv',
|
||||||
url: url,
|
url: url,
|
||||||
@ -594,12 +615,14 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
hasAudio: false,
|
hasAudio: false,
|
||||||
hasVideo: true
|
hasVideo: true
|
||||||
},
|
},
|
||||||
onCreat: initPlayer
|
onCreate: initPlayer
|
||||||
}), /*#__PURE__*/React.createElement("div", {
|
}, playerProps)), /*#__PURE__*/React.createElement("div", {
|
||||||
className: classNames("".concat(componentName, "-crop-container")),
|
className: classNames("".concat(componentName, "-crop-container")),
|
||||||
ref: corpContainerRef,
|
ref: corpContainerRef,
|
||||||
style: {
|
style: {
|
||||||
display: isFullscreen ? 'none' : 'block'
|
display: isFullscreen ? 'none' : 'block',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
}
|
}
|
||||||
}), showCrop && cropRect && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
}), showCrop && cropRect && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||||||
ref: alginContainerRef,
|
ref: alginContainerRef,
|
||||||
@ -625,27 +648,26 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
cropType: CROP_TYPE['CUSTOM']
|
cropType: CROP_TYPE['CUSTOM']
|
||||||
}))), !showCrop && /*#__PURE__*/React.createElement("div", {
|
}))), !showCrop && /*#__PURE__*/React.createElement("div", {
|
||||||
className: "".concat(componentName, "-opt")
|
className: "".concat(componentName, "-opt")
|
||||||
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Button, {
|
|
||||||
type: "text",
|
|
||||||
onClick: function onClick() {
|
|
||||||
if (!isPlay) {
|
|
||||||
var _videoInsRef$current8;
|
|
||||||
//播放中暂停
|
|
||||||
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current8 = videoInsRef.current) === null || _videoInsRef$current8 === void 0 || _videoInsRef$current8.play();
|
|
||||||
_setShowCrop(false);
|
|
||||||
} else {
|
|
||||||
var _videoInsRef$current9;
|
|
||||||
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current9 = videoInsRef.current) === null || _videoInsRef$current9 === void 0 || _videoInsRef$current9.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, /*#__PURE__*/React.createElement(IconFont, {
|
}, /*#__PURE__*/React.createElement(IconFont, {
|
||||||
styles: {
|
styles: {
|
||||||
|
marginRight: '12px',
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
display: 'flex'
|
display: 'flex'
|
||||||
},
|
},
|
||||||
|
onIconClick: function onIconClick() {
|
||||||
|
if (!isPlay) {
|
||||||
|
var _videoInsRef$current12;
|
||||||
|
//播放中暂停
|
||||||
|
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current12 = videoInsRef.current) === null || _videoInsRef$current12 === void 0 || _videoInsRef$current12.play();
|
||||||
|
_setShowCrop(false);
|
||||||
|
} else {
|
||||||
|
var _videoInsRef$current13;
|
||||||
|
videoInsRef === null || videoInsRef === void 0 || (_videoInsRef$current13 = videoInsRef.current) === null || _videoInsRef$current13 === void 0 || _videoInsRef$current13.pause();
|
||||||
|
}
|
||||||
|
},
|
||||||
color: "#1890ff",
|
color: "#1890ff",
|
||||||
icon: !isPlay ? 'icon-shipinbofang' : 'icon-shipinzanting'
|
icon: !isPlay ? 'icon-bofang3' : 'icon-zanting1'
|
||||||
}))), /*#__PURE__*/React.createElement("div", {
|
}), /*#__PURE__*/React.createElement("div", {
|
||||||
className: "".concat(componentName, "-opt-range"),
|
className: "".concat(componentName, "-opt-range"),
|
||||||
onClick: function onClick(e) {
|
onClick: function onClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -656,20 +678,19 @@ var VideoPlayer = /*#__PURE__*/forwardRef(function (props, ref) {
|
|||||||
max: showMaxDuration,
|
max: showMaxDuration,
|
||||||
showSlider: showSlider,
|
showSlider: showSlider,
|
||||||
onChange: seek
|
onChange: seek
|
||||||
}), /*#__PURE__*/React.createElement("div", null, formatDurationTime(playTime), "/", formatDurationTime(showMaxDuration))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Button, {
|
}), /*#__PURE__*/React.createElement("div", null, formatDurationTime(playTime), "/", formatDurationTime(showMaxDuration))), /*#__PURE__*/React.createElement(IconFont, {
|
||||||
type: "text",
|
styles: {
|
||||||
onClick: function onClick(e) {
|
display: 'flex',
|
||||||
|
marginLeft: '12px'
|
||||||
|
},
|
||||||
|
color: "#fff",
|
||||||
|
size: 18,
|
||||||
|
onIconClick: function onIconClick(e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
toggleFullscreen();
|
toggleFullscreen();
|
||||||
}
|
|
||||||
}, /*#__PURE__*/React.createElement(IconFont, {
|
|
||||||
styles: {
|
|
||||||
color: '#fff',
|
|
||||||
display: 'flex'
|
|
||||||
},
|
},
|
||||||
size: 18,
|
icon: isFullscreen ? 'icon-suoxiao1' : 'icon-quanping1'
|
||||||
icon: isFullscreen ? 'icon-cancle_fullscreen' : 'icon-fullscreen'
|
})), !!showStatus && /*#__PURE__*/React.createElement(Loading, {
|
||||||
})))), !!showStatus && /*#__PURE__*/React.createElement(Loading, {
|
|
||||||
status: showStatus,
|
status: showStatus,
|
||||||
reload: function reload() {
|
reload: function reload() {
|
||||||
return _reload();
|
return _reload();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
var _excluded = ["className", "autoPlay", "config", "onCreat", "playId"];
|
var _excluded = ["className", "autoPlay", "config", "onCreate", "playId"];
|
||||||
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
||||||
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
||||||
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
||||||
@ -45,12 +45,13 @@ var VideoPlayer = /*#__PURE__*/function (_Component) {
|
|||||||
autoPlay = _this$props$autoPlay === void 0 ? true : _this$props$autoPlay,
|
autoPlay = _this$props$autoPlay === void 0 ? true : _this$props$autoPlay,
|
||||||
_this$props$config = _this$props.config,
|
_this$props$config = _this$props.config,
|
||||||
config = _this$props$config === void 0 ? {} : _this$props$config,
|
config = _this$props$config === void 0 ? {} : _this$props$config,
|
||||||
onCreat = _this$props.onCreat,
|
onCreate = _this$props.onCreate,
|
||||||
playId = _this$props.playId,
|
playId = _this$props.playId,
|
||||||
others = _objectWithoutProperties(_this$props, _excluded);
|
others = _objectWithoutProperties(_this$props, _excluded);
|
||||||
if ($video) {
|
if ($video) {
|
||||||
if (flvjs.isSupported() && _this.props.url && _this.props.url) {
|
if (flvjs.isSupported() && _this.props.url && _this.props.url) {
|
||||||
var reload = function reload() {
|
var reload = function reload() {
|
||||||
|
var _this$flvPlayer;
|
||||||
if (_this.flvPlayer && _this.flvPlayer.destroy) {
|
if (_this.flvPlayer && _this.flvPlayer.destroy) {
|
||||||
try {
|
try {
|
||||||
_this.flvPlayer.destroy();
|
_this.flvPlayer.destroy();
|
||||||
@ -65,7 +66,7 @@ var VideoPlayer = /*#__PURE__*/function (_Component) {
|
|||||||
flvPlayer.load();
|
flvPlayer.load();
|
||||||
_this.flvPlayer = flvPlayer;
|
_this.flvPlayer = flvPlayer;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
var controller = _this.flvPlayer._transmuxer._controller;
|
var controller = (_this$flvPlayer = _this.flvPlayer) === null || _this$flvPlayer === void 0 || (_this$flvPlayer = _this$flvPlayer._transmuxer) === null || _this$flvPlayer === void 0 ? void 0 : _this$flvPlayer._controller;
|
||||||
var wsLoader = controller._ioctl._loader;
|
var wsLoader = controller._ioctl._loader;
|
||||||
var oldWsOnCompleteFunc = wsLoader._onComplete;
|
var oldWsOnCompleteFunc = wsLoader._onComplete;
|
||||||
wsLoader._onComplete = function () {
|
wsLoader._onComplete = function () {
|
||||||
@ -82,10 +83,9 @@ var VideoPlayer = /*#__PURE__*/function (_Component) {
|
|||||||
oldWsOnCompleteFunc();
|
oldWsOnCompleteFunc();
|
||||||
};
|
};
|
||||||
_this.flvPlayer.reload = reload;
|
_this.flvPlayer.reload = reload;
|
||||||
onCreat && onCreat(_this.flvPlayer, $video);
|
onCreate === null || onCreate === void 0 || onCreate(_this.flvPlayer, $video);
|
||||||
};
|
};
|
||||||
reload();
|
reload();
|
||||||
onCreat && onCreat(_this.flvPlayer, $video);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -95,9 +95,9 @@ var VideoPlayer = /*#__PURE__*/function (_Component) {
|
|||||||
key: "componentWillUnmount",
|
key: "componentWillUnmount",
|
||||||
value: function componentWillUnmount() {
|
value: function componentWillUnmount() {
|
||||||
if (this.flvPlayer) {
|
if (this.flvPlayer) {
|
||||||
var _this$flvPlayer, _this$flvPlayer2;
|
var _this$flvPlayer2, _this$flvPlayer3;
|
||||||
(_this$flvPlayer = this.flvPlayer) === null || _this$flvPlayer === void 0 || _this$flvPlayer.unload();
|
(_this$flvPlayer2 = this.flvPlayer) === null || _this$flvPlayer2 === void 0 || _this$flvPlayer2.unload();
|
||||||
(_this$flvPlayer2 = this.flvPlayer) === null || _this$flvPlayer2 === void 0 || _this$flvPlayer2.detachMediaElement();
|
(_this$flvPlayer3 = this.flvPlayer) === null || _this$flvPlayer3 === void 0 || _this$flvPlayer3.detachMediaElement();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@ -119,13 +119,11 @@ var VideoPlayer = /*#__PURE__*/function (_Component) {
|
|||||||
return /*#__PURE__*/React.createElement("video", {
|
return /*#__PURE__*/React.createElement("video", {
|
||||||
muted: true,
|
muted: true,
|
||||||
preload: "metadata",
|
preload: "metadata",
|
||||||
className: className
|
className: className,
|
||||||
// controls={true}
|
style: _objectSpread({
|
||||||
,
|
|
||||||
style: Object.assign({
|
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%'
|
height: '100%'
|
||||||
}, style ? style : {}),
|
}, style),
|
||||||
ref: this.initFlv
|
ref: this.initFlv
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ function _objectWithoutProperties(source, excluded) { if (source == null) return
|
|||||||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Slider } from 'antd';
|
import { Slider, ConfigProvider } from 'antd';
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
var componentName = "zhst-image__range";
|
var componentName = "zhst-image__range";
|
||||||
export var Range = function Range(props) {
|
export var Range = function Range(props) {
|
||||||
@ -15,6 +15,15 @@ export var Range = function Range(props) {
|
|||||||
return /*#__PURE__*/React.createElement("div", {
|
return /*#__PURE__*/React.createElement("div", {
|
||||||
style: style,
|
style: style,
|
||||||
className: classNames("".concat(componentName), !showSlider && "".concat(componentName, "--no-slider"), className)
|
className: classNames("".concat(componentName), !showSlider && "".concat(componentName, "--no-slider"), className)
|
||||||
}, /*#__PURE__*/React.createElement(Slider, others));
|
}, /*#__PURE__*/React.createElement(ConfigProvider, {
|
||||||
|
theme: {
|
||||||
|
components: {
|
||||||
|
Slider: {
|
||||||
|
railBg: 'rgba(255, 255, 255, 0.6)',
|
||||||
|
railHoverBg: 'rgba(255, 255, 255, 0.6)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, /*#__PURE__*/React.createElement(Slider, others)));
|
||||||
};
|
};
|
||||||
export default Range;
|
export default Range;
|
@ -1,8 +1,6 @@
|
|||||||
.zhst-image__video-view {
|
.zhst-image__video-view {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
|
||||||
height: 532px;
|
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
|
|
||||||
// &-flv {
|
// &-flv {
|
||||||
@ -37,7 +35,7 @@
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px 0 24px;
|
||||||
background-color: rgb(0 0 0 / 80%);
|
background-color: rgb(0 0 0 / 80%);
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import download from "downloadjs";
|
||||||
export function getShowStatus(isLoadingVideo, isEnd, isError) {
|
export function getShowStatus(isLoadingVideo, isEnd, isError) {
|
||||||
var status = null;
|
var status = null;
|
||||||
if (isLoadingVideo) {
|
if (isLoadingVideo) {
|
||||||
@ -10,4 +11,41 @@ export function getShowStatus(isLoadingVideo, isEnd, isError) {
|
|||||||
status = 'END';
|
status = 'END';
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 下载功能的可配置属性
|
||||||
|
|
||||||
|
// 视屏截帧、下载
|
||||||
|
export var downloadFrame = function downloadFrame(_videoDom, opt) {
|
||||||
|
var _ref = opt || {},
|
||||||
|
_ref$downloadAble = _ref.downloadAble,
|
||||||
|
downloadAble = _ref$downloadAble === void 0 ? true : _ref$downloadAble,
|
||||||
|
_ref$fileName = _ref.fileName,
|
||||||
|
fileName = _ref$fileName === void 0 ? 'image' : _ref$fileName,
|
||||||
|
_ref$fileType = _ref.fileType,
|
||||||
|
fileType = _ref$fileType === void 0 ? 'image/png' : _ref$fileType;
|
||||||
|
try {
|
||||||
|
var video = _videoDom;
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var ctx = canvas.getContext('2d');
|
||||||
|
var base64;
|
||||||
|
|
||||||
|
//当视频处于还未加载出来时,截屏为黑色图片
|
||||||
|
if (video.readyState === 0) {
|
||||||
|
ctx === null || ctx === void 0 || ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
canvas.width = video.offsetWidth;
|
||||||
|
canvas.height = video.offsetHeight;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx.fillStyle = 'black';
|
||||||
|
ctx === null || ctx === void 0 || ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
} else {
|
||||||
|
canvas.width = video.videoWidth;
|
||||||
|
canvas.height = video.videoHeight;
|
||||||
|
ctx === null || ctx === void 0 || ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
||||||
|
base64 = canvas.toDataURL(fileType);
|
||||||
|
downloadAble && download(base64, fileName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/meta",
|
"name": "@zhst/meta",
|
||||||
"version": "0.13.0",
|
"version": "0.15.0",
|
||||||
"description": "原子组件",
|
"description": "原子组件",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"meta",
|
"meta",
|
||||||
|
@ -11,9 +11,8 @@ import {
|
|||||||
getFileByRect
|
getFileByRect
|
||||||
} from '@zhst/func';
|
} from '@zhst/func';
|
||||||
import Align from 'rc-align';
|
import Align from 'rc-align';
|
||||||
import { Button, Empty } from '..';
|
import { Empty, AttachImage } from '..';
|
||||||
import { type Rect, type IScreenshotButtonProp, type AlignType } from '@zhst/types'
|
import { type Rect, type IScreenshotButtonProp, type AlignType } from '@zhst/types'
|
||||||
import { IconFont as Icon } from '@zhst/icon'
|
|
||||||
import {
|
import {
|
||||||
Cropper,
|
Cropper,
|
||||||
Viewer,
|
Viewer,
|
||||||
@ -450,10 +449,6 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================= attact img =========================
|
|
||||||
const [selectAttachImgIndex, setSelectAttachImgIndex] = useState(0);
|
|
||||||
const [isZoomin, setIsZoomin] = useState(false);
|
|
||||||
|
|
||||||
// ============================== Ref ===============================
|
// ============================== Ref ===============================
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
imgInsRef,
|
imgInsRef,
|
||||||
@ -529,62 +524,11 @@ export const BigImagePreview = React.forwardRef<ImgViewRef, ImgViewProps>((props
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* 场景图小图 */}
|
{/* 场景图小图 */}
|
||||||
{attachImg?.length && !showCrop && (
|
{attachImg?.length && !showCrop && (
|
||||||
<div
|
<AttachImage
|
||||||
className={classNames(
|
showAttachImgLabel={showAttachImgLabel}
|
||||||
`${componentName}-attach`,
|
data={attachImg}
|
||||||
isZoomin && `${componentName}-attach--zoomin`,
|
/>
|
||||||
`${componentName}-attach--fixed`,
|
|
||||||
isZoomin && `${componentName}-attach--zoomin--fixed`
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className={classNames(`${componentName}-attach__tab`)}>
|
|
||||||
{showAttachImgLabel
|
|
||||||
? attachImg?.map(({ label }, index) => (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={classNames(
|
|
||||||
`${componentName}-attach__tab-item`,
|
|
||||||
selectAttachImgIndex === index && `${componentName}-attach__tab-item--select`
|
|
||||||
)}
|
|
||||||
onMouseEnter={() => {
|
|
||||||
setSelectAttachImgIndex(index);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
: null}
|
|
||||||
</div>
|
|
||||||
<div className={classNames(`${componentName}-attach__scale`)}>
|
|
||||||
<Button
|
|
||||||
type="text"
|
|
||||||
//绝对定位下onClick事件失效采用onMouseDown
|
|
||||||
onMouseDown={(e) => {
|
|
||||||
//如果是左键执行
|
|
||||||
if (e.button == 0) {
|
|
||||||
setIsZoomin((pre) => !pre);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
color: '#fff',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
styles={{ display: 'flex' }}
|
|
||||||
icon={isZoomin ? 'icon-cancle_fullscreen' : 'icon-fullscreen'}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
draggable="false"
|
|
||||||
className={classNames(
|
|
||||||
`${componentName}-attach__img`,
|
|
||||||
`${componentName}-attach__img--fixed`
|
|
||||||
)}
|
|
||||||
src={get(attachImg, `${selectAttachImgIndex}.url`, '')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{(showScore || score) && <div
|
{(showScore || score) && <div
|
||||||
style={{ bottom: 20 }}
|
style={{ bottom: 20 }}
|
||||||
|
@ -30,21 +30,24 @@ export default {
|
|||||||
//method
|
//method
|
||||||
bind() {
|
bind() {
|
||||||
const { canvas, element, eventHandleList = [], options } = this;
|
const { canvas, element, eventHandleList = [], options } = this;
|
||||||
//图片事件
|
// 鼠标滚轮事件
|
||||||
const scaleAble = get(options, 'scaleAble', true);
|
const scaleAble = get(options, 'scaleAble', true);
|
||||||
|
|
||||||
if (scaleAble) {
|
if (scaleAble) {
|
||||||
const handleWhele = addEventListenerWrapper(canvas, EVENT_WHEEL, this.onWheel.bind(this));
|
const handleWheel = addEventListenerWrapper(canvas, EVENT_WHEEL, this.onWheel.bind(this));
|
||||||
eventHandleList.push(handleWhele);
|
eventHandleList.push(handleWheel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 鼠标 - 拖拽事件
|
||||||
const dragAble = get(options, 'dragAble', true);
|
const dragAble = get(options, 'dragAble', true);
|
||||||
|
|
||||||
if (dragAble) {
|
if (dragAble) {
|
||||||
const handleDragStart = addEventListenerWrapper(
|
const handleDragStart = addEventListenerWrapper(
|
||||||
canvas,
|
canvas,
|
||||||
EVENT_POINTER_DOWN,
|
EVENT_POINTER_DOWN,
|
||||||
this.onDragStart.bind(this)
|
this.onDragStart.bind(this)
|
||||||
);
|
);
|
||||||
eventHandleList.push(addEventListenerWrapper);
|
eventHandleList.push(handleDragStart);
|
||||||
const handleDragMove = addEventListenerWrapper(
|
const handleDragMove = addEventListenerWrapper(
|
||||||
element.ownerDocument,
|
element.ownerDocument,
|
||||||
EVENT_POINTER_MOVE,
|
EVENT_POINTER_MOVE,
|
||||||
@ -53,23 +56,23 @@ export default {
|
|||||||
eventHandleList.push(handleDragMove);
|
eventHandleList.push(handleDragMove);
|
||||||
EVENT_POINTER_UP.trim()
|
EVENT_POINTER_UP.trim()
|
||||||
.split(REGEXP_SPACES)
|
.split(REGEXP_SPACES)
|
||||||
.forEach((eventName) => {
|
.forEach((_eventName) => {
|
||||||
const handleDragEnd = addEventListenerWrapper(
|
const handleDragEnd = addEventListenerWrapper(
|
||||||
element.ownerDocument,
|
element.ownerDocument,
|
||||||
eventName,
|
_eventName,
|
||||||
this.onDragEnd.bind(this)
|
this.onDragEnd.bind(this)
|
||||||
);
|
);
|
||||||
eventHandleList.push(handleDragEnd);
|
eventHandleList.push(handleDragEnd);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//rect事件
|
// 鼠标 - 点击事件
|
||||||
const handleClick = addEventListenerWrapper(canvas, EVENT_CLICK, this.onClick.bind(this));
|
const selectAble = get(options, 'selectAble', true);
|
||||||
eventHandleList.push(handleClick);
|
|
||||||
// const handleLeveal = addEventListenerWrapper(canvas, EVENT_LEAVEL, this.onLeavel.bind(this));
|
if (selectAble) {
|
||||||
// eventHandleList.push(handleLeveal);
|
const handleClick = addEventListenerWrapper(canvas, EVENT_CLICK, this.onClick.bind(this));
|
||||||
// const handleEnter = addEventListenerWrapper(canvas, EVENT_ENTER, this.onEnter.bind(this));
|
eventHandleList.push(handleClick);
|
||||||
// eventHandleList.push(handleEnter);
|
}
|
||||||
},
|
},
|
||||||
unbind() {
|
unbind() {
|
||||||
const { eventHandleList } = this;
|
const { eventHandleList } = this;
|
||||||
@ -83,7 +86,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* 图片事件 */
|
/* 鼠标滚轮事件 */
|
||||||
onWheel(event, cropBox?) {
|
onWheel(event, cropBox?) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -123,6 +126,7 @@ export default {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 鼠标拖拽 - 开始拖拽
|
||||||
onDragStart(event) {
|
onDragStart(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
// This line is required for preventing page zooming in iOS browsers
|
// This line is required for preventing page zooming in iOS browsers
|
||||||
@ -150,6 +154,8 @@ export default {
|
|||||||
|
|
||||||
addClass(this.canvas, CLASS_MOVE);
|
addClass(this.canvas, CLASS_MOVE);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 鼠标拖拽 - 拖拽中
|
||||||
onDragMove(event) {
|
onDragMove(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@ -175,6 +181,8 @@ export default {
|
|||||||
this.pointer.startX = this.pointer.endX;
|
this.pointer.startX = this.pointer.endX;
|
||||||
this.pointer.startY = this.pointer.endY;
|
this.pointer.startY = this.pointer.endY;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 鼠标拖拽 - 停止拖拽
|
||||||
onDragEnd(event) {
|
onDragEnd(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
@ -190,14 +198,7 @@ export default {
|
|||||||
removeClass(this.canvas, CLASS_MOVE);
|
removeClass(this.canvas, CLASS_MOVE);
|
||||||
},
|
},
|
||||||
|
|
||||||
/* rect事件 */
|
// 鼠标点击
|
||||||
// onLeavel(event) {
|
|
||||||
// const pointerCenter = this.windowToCanvasAxis(event);
|
|
||||||
// this.highlightShape(pointerCenter);
|
|
||||||
// },
|
|
||||||
// onEnter(event) {
|
|
||||||
// this.highlightShape(null);
|
|
||||||
// },
|
|
||||||
onClick(event) {
|
onClick(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const pointerCenter = this.windowToCanvasAxis(event);
|
const pointerCenter = this.windowToCanvasAxis(event);
|
||||||
|
@ -1,6 +1,21 @@
|
|||||||
//@ts-nocheck
|
//@ts-nocheck
|
||||||
|
import * as turf from '@turf/turf';
|
||||||
import { AXIS_TYPE_ORIGIN, AXIS_TYPE_CANVAS, AXIS_TYPE_IMAGE } from './constants';
|
import { AXIS_TYPE_ORIGIN, AXIS_TYPE_CANVAS, AXIS_TYPE_IMAGE } from './constants';
|
||||||
|
|
||||||
|
export function rectToPolygon(axisRect: any) {
|
||||||
|
const polygon = turf.polygon([
|
||||||
|
[
|
||||||
|
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)],
|
||||||
|
[setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y, -2)],
|
||||||
|
[setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y2, -2)],
|
||||||
|
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y2, -2)],
|
||||||
|
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//设置数据的精度
|
//设置数据的精度
|
||||||
//accuracy 表示精度 以原点为中心向左为正,向右为负,
|
//accuracy 表示精度 以原点为中心向左为正,向右为负,
|
||||||
//isCeil 表示是否为向上取整
|
//isCeil 表示是否为向上取整
|
||||||
@ -28,16 +43,15 @@ export default {
|
|||||||
targetTransform: {
|
targetTransform: {
|
||||||
translateX: 0,
|
translateX: 0,
|
||||||
translateY: 0,
|
translateY: 0,
|
||||||
scale: 0,
|
scale: 1,
|
||||||
rotate: 0,
|
rotate: 0,
|
||||||
// rotate: 90,
|
// rotate: 90,
|
||||||
},
|
},
|
||||||
|
|
||||||
windowToCanvasAxis(event) {
|
windowToCanvasAxis(event) {
|
||||||
const { x, y } = this.canvas.getBoundingClientRect();
|
|
||||||
return {
|
return {
|
||||||
x: event.pageX - x,
|
x: event.offsetX,
|
||||||
y: event.pageY - y,
|
y: event.offsetY,
|
||||||
__AXIS_TYPE__: AXIS_TYPE_CANVAS,
|
__AXIS_TYPE__: AXIS_TYPE_CANVAS,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -52,7 +66,7 @@ export default {
|
|||||||
},
|
},
|
||||||
originAxisToCanvasAxis({ x, y, ...others }) {
|
originAxisToCanvasAxis({ x, y, ...others }) {
|
||||||
const { targetTransform } = this;
|
const { targetTransform } = this;
|
||||||
const { translateX, translateY, scale } = targetTransform;
|
const { translateX, translateY, scale = 1 } = targetTransform;
|
||||||
const axis = {
|
const axis = {
|
||||||
x: translateX + x * scale,
|
x: translateX + x * scale,
|
||||||
y: translateY + y * scale,
|
y: translateY + y * scale,
|
||||||
|
@ -28,6 +28,12 @@ export interface Option {
|
|||||||
*/
|
*/
|
||||||
dragAble?: boolean;
|
dragAble?: boolean;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 是否允许点击
|
||||||
|
* @default: true
|
||||||
|
*/
|
||||||
|
selectAble?: boolean;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* fit scale 作为 最小缩放
|
* fit scale 作为 最小缩放
|
||||||
* @default: false
|
* @default: false
|
||||||
|
@ -51,7 +51,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
initCanvas() {
|
initCanvas() {
|
||||||
if (!this.image) return;
|
|
||||||
//通过样式设置 不依赖父元素的prosition
|
//通过样式设置 不依赖父元素的prosition
|
||||||
const { element, canvas, limit = {}, options } = this;
|
const { element, canvas, limit = {}, options } = this;
|
||||||
const containerData = {
|
const containerData = {
|
||||||
@ -65,7 +64,7 @@ export default {
|
|||||||
const fitTransform = this.calcFitScreen();
|
const fitTransform = this.calcFitScreen();
|
||||||
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
|
this.targetTransform = Object.assign({}, this.targetTransform, fitTransform);
|
||||||
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
|
dispatchEvent(this.element, EVENT_VIEWER_TRANSFORM_CHANGE, cloneDeep(this.targetTransform));
|
||||||
//产品需求:fitscale 是minscale
|
//产品需求:fitscale 是 minscale
|
||||||
const { fitScaleAsMinScale = false } = options;
|
const { fitScaleAsMinScale = false } = options;
|
||||||
if (fitScaleAsMinScale) {
|
if (fitScaleAsMinScale) {
|
||||||
this.limit = Object.assign({ minScale: this.targetTransform.scale }, this.limit);
|
this.limit = Object.assign({ minScale: this.targetTransform.scale }, this.limit);
|
||||||
@ -86,8 +85,9 @@ export default {
|
|||||||
loop();
|
loop();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 绘制画布
|
||||||
renderCanvas(_ctx) {
|
renderCanvas(_ctx) {
|
||||||
if (!this.image || !this.canvas) return;
|
if (!this.canvas) return;
|
||||||
const { containerData, canvas, targetTransform, options } = this;
|
const { containerData, canvas, targetTransform, options } = this;
|
||||||
const { translateX, translateY, scale, rotate } = targetTransform;
|
const { translateX, translateY, scale, rotate } = targetTransform;
|
||||||
const ctx = _ctx ? _ctx : canvas.getContext('2d');
|
const ctx = _ctx ? _ctx : canvas.getContext('2d');
|
||||||
@ -102,14 +102,14 @@ export default {
|
|||||||
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
||||||
// ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
// ctx.setTransform(scale, 0, 0, scale, translateX, translateY);
|
||||||
//旋转
|
//旋转
|
||||||
const centerX = this.image.width / 2;
|
const centerX = this.image ? this.image.width / 2 : canvas.width;
|
||||||
const centerY = this.image.height / 2;
|
const centerY = this.image ? this.image.height / 2 : canvas.height;
|
||||||
ctx.translate(centerX, centerY);
|
ctx.translate(centerX, centerY);
|
||||||
ctx.rotate((rotate / 180) * Math.PI);
|
ctx.rotate((rotate / 180) * Math.PI);
|
||||||
ctx.translate(-centerX, -centerY);
|
ctx.translate(-centerX, -centerY);
|
||||||
|
|
||||||
//图片
|
//图片
|
||||||
ctx.drawImage(this.image, 0, 0);
|
this.image && ctx.drawImage(this.image, 0, 0);
|
||||||
|
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
//画图形
|
//画图形
|
||||||
|
@ -2,22 +2,10 @@
|
|||||||
import { isNil, isArray, isFunction } from '@zhst/func';
|
import { isNil, isArray, isFunction } from '@zhst/func';
|
||||||
import * as turf from '@turf/turf';
|
import * as turf from '@turf/turf';
|
||||||
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
|
||||||
import { setNumberAccuracy } from './helper';
|
import { rectToPolygon } from './helper';
|
||||||
import { SHAPE_TYPE_RECT, SHAPE_TYPE_CIRCLE, EVENT_SHAPE_SELECT } from './constants';
|
import { SHAPE_TYPE_RECT, SHAPE_TYPE_CIRCLE, EVENT_SHAPE_SELECT } from './constants';
|
||||||
import { dispatchEvent } from '../utils';
|
import { dispatchEvent } from '../utils';
|
||||||
|
|
||||||
function rectToPolygon(axisRect: any) {
|
|
||||||
const polygon = turf.polygon([
|
|
||||||
[
|
|
||||||
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)],
|
|
||||||
[setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y, -2)],
|
|
||||||
[setNumberAccuracy(axisRect.x2, -2), setNumberAccuracy(axisRect.y2, -2)],
|
|
||||||
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y2, -2)],
|
|
||||||
[setNumberAccuracy(axisRect.x, -2), setNumberAccuracy(axisRect.y, -2)],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
export interface Shape {
|
export interface Shape {
|
||||||
id?: number | string; //uuid
|
id?: number | string; //uuid
|
||||||
selectAble?: boolean;
|
selectAble?: boolean;
|
||||||
@ -64,14 +52,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//method
|
//method:添加矩形
|
||||||
addShape(shap: Shape | Array<Shape>, type = SHAPE_TYPE_RECT) {
|
addShape(shape: Shape | Array<Shape>, type = SHAPE_TYPE_RECT) {
|
||||||
this.color = shap.color ? shap.color : '';
|
this.color = shape.color ? shape.color : '';
|
||||||
if (isNil(shap) || this.disableAdd) return;
|
|
||||||
|
if (isNil(shape) || this.disableAdd) return;
|
||||||
const { shapeList: preShapeList = [] } = this;
|
const { shapeList: preShapeList = [] } = this;
|
||||||
let shapList = isArray(shap) ? shap : [shap];
|
let _shapeList = isArray(shape) ? shape : [shape];
|
||||||
shapList = shapList.map((v) => ({ ...v, __SHAPE_TYPE__: type }));
|
_shapeList = _shapeList.map((v) => ({ ...v, __SHAPE_TYPE__: type }));
|
||||||
this.shapeList = [...preShapeList, ...shapList];
|
this.shapeList = [...preShapeList, ..._shapeList];
|
||||||
},
|
},
|
||||||
//
|
//
|
||||||
setSelectShapId(id: number) {
|
setSelectShapId(id: number) {
|
||||||
@ -226,9 +215,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 绘制矩形
|
||||||
renderRect(ctx, shape, type) {
|
renderRect(ctx, shape, type) {
|
||||||
//算rect
|
//算rect
|
||||||
const axisRect = this.imgRectAxisToCanvasAxisRect(shape);
|
const axisRect = this.imgRectAxisToCanvasAxisRect({ ...shape, image: ctx.canvas});
|
||||||
const rect = {
|
const rect = {
|
||||||
x: axisRect.x2 > axisRect.x ? axisRect.x : axisRect.x2,
|
x: axisRect.x2 > axisRect.x ? axisRect.x : axisRect.x2,
|
||||||
y: axisRect.y2 > axisRect.y ? axisRect.y : axisRect.y2,
|
y: axisRect.y2 > axisRect.y ? axisRect.y : axisRect.y2,
|
||||||
|
@ -7,25 +7,26 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
toRealNumber,
|
toRealNumber,
|
||||||
getTransforms,
|
getTransforms,
|
||||||
formatDurationTime
|
formatDurationTime,
|
||||||
} from '@zhst/func';
|
} from '@zhst/func';
|
||||||
import Align from 'rc-align';
|
import Align from 'rc-align';
|
||||||
|
import flvJs from 'flv.js'
|
||||||
import { Rect, IScreenshotButtonProp, AlignType } from '@zhst/types'
|
import { Rect, IScreenshotButtonProp, AlignType } from '@zhst/types'
|
||||||
import { useLatest, useUpdateEffect, useFullscreen, useUnmount } from '@zhst/hooks';
|
import { useLatest, useUpdateEffect, useFullscreen, useUnmount } from '@zhst/hooks';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import download from 'downloadjs';
|
import { message } from '..';
|
||||||
import { Button, message } from '..';
|
|
||||||
import { IconFont } from '@zhst/icon';
|
import { IconFont } from '@zhst/icon';
|
||||||
import {
|
import {
|
||||||
Cropper,
|
Cropper,
|
||||||
EVENT_CROP_START,
|
EVENT_CROP_START,
|
||||||
EVENT_CROP_END,
|
EVENT_CROP_END,
|
||||||
|
Viewer,
|
||||||
} from '../ImageEditor';
|
} from '../ImageEditor';
|
||||||
import FlvPlayer, { FLV_EVENT } from './components/FlvPlayer';
|
import FlvPlayer, { FLV_EVENT } from './components/FlvPlayer';
|
||||||
import Range from './components/Progress';
|
import Range from './components/Progress';
|
||||||
import Loading from './components/Loading';
|
import Loading from './components/Loading';
|
||||||
import { CROP_TYPE } from '../utils/constants';
|
import { CROP_TYPE } from '../utils/constants';
|
||||||
import { getShowStatus } from './videoPlayerHelper'
|
import { downloadFrame, DownloadFrameOptionProps, getShowStatus } from './videoPlayerHelper'
|
||||||
import './index.less'
|
import './index.less'
|
||||||
|
|
||||||
const componentName = `zhst-image__video-view`;
|
const componentName = `zhst-image__video-view`;
|
||||||
@ -33,8 +34,21 @@ const componentName = `zhst-image__video-view`;
|
|||||||
export interface VideoViewProps {
|
export interface VideoViewProps {
|
||||||
/* 播放地址 */
|
/* 播放地址 */
|
||||||
url: string;
|
url: string;
|
||||||
|
width?: string;
|
||||||
|
height?: string;
|
||||||
|
backgroundColor?: string; // 背景颜色
|
||||||
|
autoPlay?: boolean; // 自动播放
|
||||||
|
showOD?: boolean;
|
||||||
|
odList?: {
|
||||||
|
id: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
w: number;
|
||||||
|
h: number;
|
||||||
|
selectAble?: boolean;
|
||||||
|
}[]
|
||||||
/* 播放总时间 */
|
/* 播放总时间 */
|
||||||
maxDuration?: number;
|
maxDuration?: number; // 最大播放时长
|
||||||
/* 截图渲染 */
|
/* 截图渲染 */
|
||||||
screenshotButtonAlign?: AlignType;
|
screenshotButtonAlign?: AlignType;
|
||||||
screenshotButtonRender?: (screenshotButtonProp: IScreenshotButtonProp) => ReactElement;
|
screenshotButtonRender?: (screenshotButtonProp: IScreenshotButtonProp) => ReactElement;
|
||||||
@ -42,13 +56,18 @@ export interface VideoViewProps {
|
|||||||
defautlNormalizationRect?: Rect;
|
defautlNormalizationRect?: Rect;
|
||||||
/* 截图回调 */
|
/* 截图回调 */
|
||||||
onCropChange?: (showCrop: boolean, normalizationRect: null | Rect) => void;
|
onCropChange?: (showCrop: boolean, normalizationRect: null | Rect) => void;
|
||||||
|
playerProps?: flvJs.Player
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface VideoViewRef {
|
export interface VideoViewRef {
|
||||||
/* 当前图片模式 */
|
/* 当前图片模式 */
|
||||||
cropAble: boolean;
|
cropAble: boolean;
|
||||||
setShowCrop: Dispatch<SetStateAction<boolean>>;
|
setShowCrop: Dispatch<SetStateAction<boolean>>;
|
||||||
downloadVideoframe: () => void;
|
downloadVideoFrame: (opt?: DownloadFrameOptionProps) => void; // 视频截帧
|
||||||
|
pause: () => void;
|
||||||
|
play: () => void;
|
||||||
|
reload: () => void; // 重新加载
|
||||||
}
|
}
|
||||||
|
|
||||||
const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
||||||
@ -63,19 +82,26 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
adjustY: true,
|
adjustY: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
autoPlay = false,
|
||||||
|
odList,
|
||||||
|
showOD,
|
||||||
|
width = '100%',
|
||||||
|
height = '532px',
|
||||||
|
backgroundColor = '#333',
|
||||||
screenshotButtonRender = () => <div style={{ color: '#fff', width: '80px', top: 0 }}>回调DOM</div>,
|
screenshotButtonRender = () => <div style={{ color: '#fff', width: '80px', top: 0 }}>回调DOM</div>,
|
||||||
onCropChange,
|
onCropChange,
|
||||||
defautlNormalizationRect: defaultNormalizationRect,
|
defautlNormalizationRect: defaultNormalizationRect,
|
||||||
|
playerProps,
|
||||||
} = props;
|
} = props;
|
||||||
// ========================== 播放 =========================
|
// ========================== 播放 =========================
|
||||||
//实例参数
|
//实例参数
|
||||||
const containerRef: any = useRef(null); //容器ref
|
const containerRef: any = useRef(null); //容器ref
|
||||||
const videoRef: any = useRef(null); //video 标签dom
|
const videoRef: any = useRef(null); //video 标签dom
|
||||||
const videoInsRef: any = useRef(null); //flv 实例
|
const videoInsRef: any = useRef(null); //flv 实例
|
||||||
const [playSeq, setPlaySeq] = useState(0); // 通过重置playid使FLV组件重新渲染
|
const [playSeq, setPlaySeq] = useState(0); // 通过重置playid使FLV组件重新渲染
|
||||||
const videoRemoveListener = useRef(noop); //移除dom监听的中间函数
|
const videoRemoveListener = useRef(noop); //移除dom监听的中间函数
|
||||||
const loadingTimeRef = useRef<number | null>(0); //最后一次加载时间
|
const loadingTimeRef = useRef<number | null>(0); //最后一次加载时间
|
||||||
const delayLoadingTimer: any = useRef(null); //算loading的定时器
|
const delayLoadingTimer: any = useRef(null); //算loading的定时器
|
||||||
//状态参数
|
//状态参数
|
||||||
const [isReady, setIsReady] = useState(false); //
|
const [isReady, setIsReady] = useState(false); //
|
||||||
const [isPlay, setIsPlay] = useState(false); //当前是否播放
|
const [isPlay, setIsPlay] = useState(false); //当前是否播放
|
||||||
@ -146,6 +172,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
const latestMaxDuration = useLatest(maxDuration);
|
const latestMaxDuration = useLatest(maxDuration);
|
||||||
|
|
||||||
const initPlayer = useCallback((ins: any, dom: any) => {
|
const initPlayer = useCallback((ins: any, dom: any) => {
|
||||||
videoRef.current = dom;
|
videoRef.current = dom;
|
||||||
videoInsRef.current = ins;
|
videoInsRef.current = ins;
|
||||||
@ -248,6 +275,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 重新加载
|
||||||
const reload = async () => {
|
const reload = async () => {
|
||||||
if (videoInsRef.current) {
|
if (videoInsRef.current) {
|
||||||
let oldTime = videoInsRef.current.currentTime;
|
let oldTime = videoInsRef.current.currentTime;
|
||||||
@ -279,6 +307,8 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
setPlayTime(0);
|
setPlayTime(0);
|
||||||
setIsEnd(false);
|
setIsEnd(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 进度条操作
|
||||||
const seek = (v: number) => {
|
const seek = (v: number) => {
|
||||||
if (videoInsRef.current && isVideoLoadFinished) {
|
if (videoInsRef.current && isVideoLoadFinished) {
|
||||||
setPlayTime(parseFloat(v as any));
|
setPlayTime(parseFloat(v as any));
|
||||||
@ -287,6 +317,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
message.warning('待视频加载完,才可操作进度条')
|
message.warning('待视频加载完,才可操作进度条')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========================== 视频opt bar =========================
|
// ========================== 视频opt bar =========================
|
||||||
const [isFullscreen, { toggleFullscreen }] = useFullscreen(containerRef, {
|
const [isFullscreen, { toggleFullscreen }] = useFullscreen(containerRef, {
|
||||||
pageFullscreen: true,
|
pageFullscreen: true,
|
||||||
@ -318,15 +349,14 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
const alignRef: any = useRef(null);
|
const alignRef: any = useRef(null);
|
||||||
const [cropRect, setCropRect] = useState<Rect| null>(null);
|
const [cropRect, setCropRect] = useState<Rect| null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
// 监听showCrop, isReady - 是否可编辑、视频播放组件是否挂载
|
||||||
showCrop ? videoInsRef?.current?.pause() : videoInsRef?.current?.play();
|
|
||||||
}, [showCrop]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let handlerCropStart: { remove: () => void; };
|
let handlerCropStart: { remove: () => void; };
|
||||||
let handlerCropEnd: { remove: () => void; };
|
let handlerCropEnd: { remove: () => void; };
|
||||||
setCropRect(null);
|
setCropRect(null);
|
||||||
|
|
||||||
if (!isReady) return;
|
if (!isReady) return;
|
||||||
|
|
||||||
if (showCrop) {
|
if (showCrop) {
|
||||||
handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, () => {
|
handlerCropStart = addEventListenerWrapper(corpContainerRef.current, EVENT_CROP_START, () => {
|
||||||
setCropRect(null);
|
setCropRect(null);
|
||||||
@ -384,12 +414,32 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
}
|
}
|
||||||
isFirstFlagRef.current = false;
|
isFirstFlagRef.current = false;
|
||||||
|
|
||||||
|
// 初始化圈选工具
|
||||||
cropInsRef.current = new Cropper(corpContainerRef.current, {
|
cropInsRef.current = new Cropper(corpContainerRef.current, {
|
||||||
showMask: true,
|
showMask: true,
|
||||||
cropBoxLimited,
|
cropBoxLimited,
|
||||||
|
editAble: false,
|
||||||
img: imageData,
|
img: imageData,
|
||||||
initialCropBoxData,
|
initialCropBoxData,
|
||||||
});
|
});
|
||||||
|
videoInsRef?.current?.pause()
|
||||||
|
} else {
|
||||||
|
const _element = videoInsRef.current._mediaElement || {}
|
||||||
|
videoInsRef?.current?.play()
|
||||||
|
// 挂载图片选择
|
||||||
|
cropInsRef.current = new Viewer(corpContainerRef.current!!, {
|
||||||
|
scaleAble: false,
|
||||||
|
selectAble: false,
|
||||||
|
dragAble: false,
|
||||||
|
width: _element.clientWidth,
|
||||||
|
height: _element.clientHeight,
|
||||||
|
backgroundColor: 'transparent'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 判定是否存在od框
|
||||||
|
showOD && odList?.forEach(_od => {
|
||||||
|
cropInsRef?.current?.addShape(_od);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
handlerCropStart?.remove();
|
handlerCropStart?.remove();
|
||||||
@ -454,7 +504,7 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//回调
|
// 监听showCrop、cropRect - 监听是否可编辑、绘制的矩形
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//计算归一化crop rect
|
//计算归一化crop rect
|
||||||
let normalizationRect = null;
|
let normalizationRect = null;
|
||||||
@ -484,32 +534,9 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
}, [showCrop, cropRect]);
|
}, [showCrop, cropRect]);
|
||||||
|
|
||||||
// ========================== 截帧 =========================
|
// ========================== 截帧 =========================
|
||||||
const downloadVideoframe = useCallback(async () => {
|
const downloadVideoFrame = useCallback((opt?: DownloadFrameOptionProps) => {
|
||||||
try {
|
|
||||||
videoInsRef?.current?.pause?.();
|
videoInsRef?.current?.pause?.();
|
||||||
let video: any = videoRef.current;
|
downloadFrame(videoRef.current, opt)
|
||||||
var canvas = document.createElement('canvas');
|
|
||||||
const ctx = canvas.getContext('2d')
|
|
||||||
let base64;
|
|
||||||
//当视频处于还未加载出来时,截屏为黑色图片
|
|
||||||
if (video.readyState === 0) {
|
|
||||||
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
canvas.width = video.offsetWidth;
|
|
||||||
canvas.height = video.offsetHeight;
|
|
||||||
// @ts-ignore
|
|
||||||
ctx.fillStyle = 'black';
|
|
||||||
ctx?.fillRect(0, 0, canvas.width, canvas.height);
|
|
||||||
base64 = canvas.toDataURL();
|
|
||||||
} else {
|
|
||||||
canvas.width = video.videoWidth;
|
|
||||||
canvas.height = video.videoHeight;
|
|
||||||
ctx?.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
||||||
base64 = canvas.toDataURL('image/png');
|
|
||||||
}
|
|
||||||
download(base64);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// ============================== 暴露出去的方法 ===============================
|
// ============================== 暴露出去的方法 ===============================
|
||||||
@ -520,18 +547,33 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
setShowCrop: (dispatch) => {
|
setShowCrop: (dispatch) => {
|
||||||
const isReady = latestIsReady.current;
|
const isReady = latestIsReady.current;
|
||||||
if (!isReady) return;
|
if (!isReady) return;
|
||||||
setShowCrop(dispatch);
|
setShowCrop?.(dispatch);
|
||||||
},
|
},
|
||||||
downloadVideoframe,
|
downloadVideoFrame,
|
||||||
|
pause: () => {
|
||||||
|
videoInsRef.current?.pause?.();
|
||||||
|
},
|
||||||
|
play: () => {
|
||||||
|
videoInsRef.current?.play?.();
|
||||||
|
},
|
||||||
|
reload
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(`${componentName}`)} ref={containerRef}>
|
<div
|
||||||
|
className={classNames(`${componentName}`)}
|
||||||
|
ref={containerRef}
|
||||||
|
style={{
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
backgroundColor
|
||||||
|
}}
|
||||||
|
>
|
||||||
{url && (
|
{url && (
|
||||||
<>
|
<>
|
||||||
<FlvPlayer
|
<FlvPlayer
|
||||||
playId={playSeq}
|
playId={playSeq}
|
||||||
autoPlay={true}
|
autoPlay={autoPlay}
|
||||||
className={classNames(`${componentName}-flv`)}
|
className={classNames(`${componentName}-flv`)}
|
||||||
type={url.startsWith('http') ? 'mp4' : 'flv'}
|
type={url.startsWith('http') ? 'mp4' : 'flv'}
|
||||||
url={url}
|
url={url}
|
||||||
@ -542,7 +584,8 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
hasAudio: false,
|
hasAudio: false,
|
||||||
hasVideo: true,
|
hasVideo: true,
|
||||||
}}
|
}}
|
||||||
onCreat={initPlayer}
|
onCreate={initPlayer}
|
||||||
|
{...playerProps}
|
||||||
/>
|
/>
|
||||||
{/* //截图 */}
|
{/* //截图 */}
|
||||||
<div
|
<div
|
||||||
@ -550,10 +593,12 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
ref={corpContainerRef}
|
ref={corpContainerRef}
|
||||||
style={{
|
style={{
|
||||||
display: isFullscreen ? 'none' : 'block',
|
display: isFullscreen ? 'none' : 'block',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <div ref={corpRef}></div> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
{/* OD控件工具 */}
|
||||||
{showCrop && cropRect && (
|
{showCrop && cropRect && (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
@ -587,32 +632,27 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
</Align>
|
</Align>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* 视频进度条 */}
|
{/* 视频工具栏 */}
|
||||||
{!showCrop && (
|
{!showCrop && (
|
||||||
<div className={`${componentName}-opt`}>
|
<div className={`${componentName}-opt`}>
|
||||||
<div>
|
<IconFont
|
||||||
<Button
|
styles={{
|
||||||
type="text"
|
marginRight: '12px',
|
||||||
onClick={() => {
|
color: '#fff',
|
||||||
if (!isPlay) {
|
display: 'flex',
|
||||||
//播放中暂停
|
}}
|
||||||
videoInsRef?.current?.play();
|
onIconClick={() => {
|
||||||
setShowCrop(false);
|
if (!isPlay) {
|
||||||
} else {
|
//播放中暂停
|
||||||
videoInsRef?.current?.pause();
|
videoInsRef?.current?.play();
|
||||||
}
|
setShowCrop(false);
|
||||||
}}
|
} else {
|
||||||
>
|
videoInsRef?.current?.pause();
|
||||||
<IconFont
|
}
|
||||||
styles={{
|
}}
|
||||||
color: '#fff',
|
color="#1890ff"
|
||||||
display: 'flex',
|
icon={!isPlay ? 'icon-bofang3' : 'icon-zanting1'}
|
||||||
}}
|
/>
|
||||||
color="#1890ff"
|
|
||||||
icon={!isPlay ? 'icon-shipinbofang' : 'icon-shipinzanting'}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className={`${componentName}-opt-range`}
|
className={`${componentName}-opt-range`}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -631,24 +671,19 @@ const VideoPlayer = forwardRef<VideoViewRef, VideoViewProps>((props, ref) => {
|
|||||||
{formatDurationTime(playTime)}/{formatDurationTime(showMaxDuration)}
|
{formatDurationTime(playTime)}/{formatDurationTime(showMaxDuration)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<IconFont
|
||||||
<Button
|
styles={{
|
||||||
type="text"
|
display: 'flex',
|
||||||
onClick={(e) => {
|
marginLeft: '12px'
|
||||||
e.stopPropagation();
|
}}
|
||||||
toggleFullscreen();
|
color="#fff"
|
||||||
}}
|
size={18}
|
||||||
>
|
onIconClick={(e) => {
|
||||||
<IconFont
|
e.stopPropagation();
|
||||||
styles={{
|
toggleFullscreen();
|
||||||
color: '#fff',
|
}}
|
||||||
display: 'flex',
|
icon={isFullscreen ? 'icon-suoxiao1' : 'icon-quanping1'}
|
||||||
}}
|
/>
|
||||||
size={18}
|
|
||||||
icon={isFullscreen ? 'icon-cancle_fullscreen' : 'icon-fullscreen'}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{/* mask */}
|
{/* mask */}
|
||||||
|
@ -20,7 +20,7 @@ export interface VideoPlayerProps {
|
|||||||
filesize?: number;
|
filesize?: number;
|
||||||
url?: string;
|
url?: string;
|
||||||
autoPlay?: boolean;
|
autoPlay?: boolean;
|
||||||
onCreat?: any;
|
onCreate?: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://github.com/Bilibili/flv.js/blob/master/docs/api.md#config
|
* @see https://github.com/Bilibili/flv.js/blob/master/docs/api.md#config
|
||||||
@ -33,7 +33,7 @@ export default class VideoPlayer extends Component<VideoPlayerProps, any> {
|
|||||||
curPlayUrl: '',
|
curPlayUrl: '',
|
||||||
shouldReinit: false,
|
shouldReinit: false,
|
||||||
};
|
};
|
||||||
flvPlayer: any = null;
|
flvPlayer: flvjs.Player & { reload?: () => void; } | null = null;
|
||||||
videoElement = null;
|
videoElement = null;
|
||||||
|
|
||||||
static getDerivedStateFromProps = (nextProps: { url?: any; playId?: any; }, prevState: { curPlayUrl?: any; playId?: any; }) => {
|
static getDerivedStateFromProps = (nextProps: { url?: any; playId?: any; }, prevState: { curPlayUrl?: any; playId?: any; }) => {
|
||||||
@ -55,7 +55,7 @@ export default class VideoPlayer extends Component<VideoPlayerProps, any> {
|
|||||||
|
|
||||||
initFlv = ($video: null) => {
|
initFlv = ($video: null) => {
|
||||||
this.videoElement = $video;
|
this.videoElement = $video;
|
||||||
const { className, autoPlay = true, config = {}, onCreat, playId, ...others } = this.props;
|
const { className, autoPlay = true, config = {}, onCreate, playId, ...others } = this.props;
|
||||||
|
|
||||||
if ($video) {
|
if ($video) {
|
||||||
|
|
||||||
@ -77,27 +77,27 @@ export default class VideoPlayer extends Component<VideoPlayerProps, any> {
|
|||||||
flvPlayer.load();
|
flvPlayer.load();
|
||||||
this.flvPlayer = flvPlayer;
|
this.flvPlayer = flvPlayer;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let controller = this.flvPlayer._transmuxer._controller
|
let controller = this.flvPlayer?._transmuxer?._controller
|
||||||
let wsLoader = controller._ioctl._loader
|
let wsLoader = controller._ioctl._loader
|
||||||
const oldWsOnCompleteFunc = wsLoader._onComplete
|
const oldWsOnCompleteFunc = wsLoader._onComplete
|
||||||
wsLoader._onComplete = function() {
|
wsLoader._onComplete = function() {
|
||||||
|
|
||||||
if(!controller._remuxer) {
|
if(!controller._remuxer) {
|
||||||
controller._remuxer = {
|
controller._remuxer = {
|
||||||
destroy: () => {
|
destroy: () => {
|
||||||
console.log('组件销毁')
|
console.log('组件销毁')
|
||||||
},
|
},
|
||||||
flushStashedSamples: () => {
|
flushStashedSamples: () => {
|
||||||
console.log("flushStashedSamples")
|
console.log("flushStashedSamples")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oldWsOnCompleteFunc()
|
oldWsOnCompleteFunc()
|
||||||
}
|
}
|
||||||
this.flvPlayer.reload = reload;
|
this.flvPlayer.reload = reload;
|
||||||
onCreat && onCreat(this.flvPlayer, $video);
|
onCreate?.(this.flvPlayer, $video);
|
||||||
};
|
};
|
||||||
reload();
|
reload();
|
||||||
onCreat && onCreat(this.flvPlayer, $video);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -121,14 +121,11 @@ export default class VideoPlayer extends Component<VideoPlayerProps, any> {
|
|||||||
muted
|
muted
|
||||||
preload="metadata"
|
preload="metadata"
|
||||||
className={className}
|
className={className}
|
||||||
// controls={true}
|
style={{
|
||||||
style={Object.assign(
|
width: '100%',
|
||||||
{
|
height: '100%',
|
||||||
width: '100%',
|
...style
|
||||||
height: '100%',
|
}}
|
||||||
},
|
|
||||||
style ? style : {}
|
|
||||||
)}
|
|
||||||
ref={this.initFlv}
|
ref={this.initFlv}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import React, { forwardRef, useContext, useEffect, useImperativeHandle, useRef } from 'react'
|
||||||
|
import flvJs from 'flv.js'
|
||||||
|
import { ConfigProvider } from '../../..'
|
||||||
|
|
||||||
|
export interface FlvPlayerProps {
|
||||||
|
prefixCls?: string;
|
||||||
|
className?: string;
|
||||||
|
autoPlay?: boolean;
|
||||||
|
config?: flvJs.Config
|
||||||
|
onCreate?: () => void;
|
||||||
|
playId?: string;
|
||||||
|
url: string;
|
||||||
|
type: string;
|
||||||
|
style?: React.CSSProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FlvPlayerRefProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
const { ConfigContext } = ConfigProvider
|
||||||
|
|
||||||
|
const FlvPlayer = forwardRef<FlvPlayerRefProps, FlvPlayerProps>((props, ref) => {
|
||||||
|
const {
|
||||||
|
prefixCls: customizePrefixCls
|
||||||
|
} = props
|
||||||
|
const {
|
||||||
|
className,
|
||||||
|
autoPlay = true,
|
||||||
|
config = {},
|
||||||
|
onCreate,
|
||||||
|
url,
|
||||||
|
style,
|
||||||
|
type = 'flv',
|
||||||
|
playId,
|
||||||
|
...others
|
||||||
|
} = props;
|
||||||
|
const { getPrefixCls } = useContext(ConfigContext);
|
||||||
|
const componentName = getPrefixCls('cropper-view', customizePrefixCls);
|
||||||
|
const flvPlayerRef = useRef<flvJs.Player>()
|
||||||
|
|
||||||
|
// 初始化播放器
|
||||||
|
useEffect(() => {
|
||||||
|
if (flvJs.isSupported() && url) {
|
||||||
|
if (flvPlayerRef.current && flvPlayerRef.current.destroy) {
|
||||||
|
try {
|
||||||
|
flvPlayerRef.current.destroy()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let flvPlayer = flvJs.createPlayer({
|
||||||
|
type: url.startsWith('http') ? 'mp4' : 'flv',
|
||||||
|
...others
|
||||||
|
}, {
|
||||||
|
deferLoadAfterSourceOpen: false,
|
||||||
|
...config
|
||||||
|
});
|
||||||
|
// @ts-ignore
|
||||||
|
flvPlayer.attachMediaElement(flvPlayerRef.current);
|
||||||
|
flvPlayer.load();
|
||||||
|
flvPlayerRef.current = flvPlayer;
|
||||||
|
// @ts-ignore
|
||||||
|
let controller = flvPlayerRef.current?._transmuxer?._controller
|
||||||
|
let wsLoader = controller._ioctl._loader
|
||||||
|
const oldWsOnCompleteFunc = wsLoader._onComplete
|
||||||
|
wsLoader._onComplete = function() {
|
||||||
|
|
||||||
|
if(!controller._remuxer) {
|
||||||
|
controller._remuxer = {
|
||||||
|
destroy: () => {
|
||||||
|
console.log('组件销毁')
|
||||||
|
},
|
||||||
|
flushStashedSamples: () => {
|
||||||
|
console.log("flushStashedSamples")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldWsOnCompleteFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
player: flvPlayerRef
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={componentName}
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
muted
|
||||||
|
preload="metadata"
|
||||||
|
className={className}
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
...style
|
||||||
|
}}
|
||||||
|
ref={flvPlayerRef}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default FlvPlayer
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Slider } from 'antd';
|
import { Slider, ConfigProvider } from 'antd';
|
||||||
import type { SliderSingleProps } from 'antd'
|
import type { SliderSingleProps } from 'antd'
|
||||||
import './index.less';
|
import './index.less';
|
||||||
|
|
||||||
@ -24,7 +24,18 @@ export const Range: React.FC<RangeWrapperProps> = (props) => {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
<Slider {...others}></Slider>
|
<ConfigProvider
|
||||||
|
theme={{
|
||||||
|
components: {
|
||||||
|
Slider: {
|
||||||
|
railBg: 'rgba(255, 255, 255, 0.6)',
|
||||||
|
railHoverBg: 'rgba(255, 255, 255, 0.6)',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Slider {...others}></Slider>
|
||||||
|
</ConfigProvider>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,44 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useRef, useState } from 'react';
|
||||||
import { VideoPlayer, Space, Button } from '@zhst/meta'
|
import { VideoPlayer, Space, Button, VideoViewRef } from '@zhst/meta'
|
||||||
|
import { VIDEO_URL } from './mock'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const videoRef = useRef(null)
|
const videoRef = useRef<VideoViewRef>(null)
|
||||||
const [url, setUrl] = useState(null)
|
const [url] = useState(VIDEO_URL)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Space>
|
<Space direction='vertical'>
|
||||||
<Space>
|
<Space>
|
||||||
<Button onClick={() => setUrl('ws://10.0.0.120:9033/flv/HaikangNvr/45.flv?ip=10.0.2.103&stime=1712539148&etime=1712539168')}>播放</Button>
|
<Button onClick={() => videoRef.current?.play()}>播放</Button>
|
||||||
|
<Button onClick={() => videoRef.current?.pause()}>暂停</Button>
|
||||||
<Button onClick={() => videoRef.current?.setShowCrop(true)}>截图</Button>
|
<Button onClick={() => videoRef.current?.setShowCrop(true)}>截图</Button>
|
||||||
<Button onClick={() => videoRef.current?.setShowCrop(false)}>取消</Button>
|
<Button onClick={() => videoRef.current?.setShowCrop(false)}>退出截图</Button>
|
||||||
|
<Button onClick={() => videoRef.current?.downloadVideoFrame()}>下载截图</Button>
|
||||||
</Space>
|
</Space>
|
||||||
{url && <VideoPlayer ref={videoRef} url={url} />}
|
<div style={{ width: '800px' }}>
|
||||||
|
<VideoPlayer
|
||||||
|
ref={videoRef}
|
||||||
|
url={url}
|
||||||
|
showOD
|
||||||
|
odList={[
|
||||||
|
{
|
||||||
|
"id": "123",
|
||||||
|
"x": 0.5519352,
|
||||||
|
"y": 0.2965385,
|
||||||
|
"w": 0.05185461,
|
||||||
|
"h": 0.24698898,
|
||||||
|
selectAble: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "456",
|
||||||
|
"x": 0.58543766,
|
||||||
|
"y": 0.3203356,
|
||||||
|
"w": 0.052037954,
|
||||||
|
"h": 0.2664015
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</Space>
|
</Space>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
1
packages/meta/src/VideoPlayer/demo/mock.ts
Normal file
1
packages/meta/src/VideoPlayer/demo/mock.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const VIDEO_URL = `ws://10.0.0.7:9033/flv/File/test/test_h264_${Math.floor(Math.random() * 6) + 1}.mp4.flv?ip=127.0.0.1`
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useRef, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { VideoPlayer, Space, Button, Row, Col, InputNumber } from '@zhst/meta'
|
import { VideoPlayer, Space, Button, Row, Col, InputNumber } from '@zhst/meta'
|
||||||
|
import { VIDEO_URL } from './mock'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const [urls, setUrls] = useState<string[]>([])
|
const [urls, setUrls] = useState<string[]>([])
|
||||||
@ -8,7 +9,7 @@ export default () => {
|
|||||||
const handlePlay = () => {
|
const handlePlay = () => {
|
||||||
let arr = []
|
let arr = []
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
arr.push(`ws://10.0.0.7:9033/flv/File/test/test_h264_${Math.floor(Math.random() * 6) + 1}.mp4.flv?ip=127.0.0.1`)
|
arr.push(VIDEO_URL)
|
||||||
}
|
}
|
||||||
setUrls(arr)
|
setUrls(arr)
|
||||||
}
|
}
|
||||||
@ -16,12 +17,12 @@ export default () => {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Space>
|
<Space>
|
||||||
<InputNumber value={num} onChange={(_num: React.SetStateAction<number>) => setNum(_num)} />
|
<InputNumber value={num} onChange={(_num) => setNum(_num!!)} />
|
||||||
<Button onClick={() => handlePlay()}>播放</Button>
|
<Button onClick={() => handlePlay()}>播放</Button>
|
||||||
<Button onClick={() => setUrls([])}>停止</Button>
|
<Button onClick={() => setUrls([])}>停止</Button>
|
||||||
</Space>
|
</Space>
|
||||||
<Row gutter={[16,16]}>
|
<Row gutter={[16,16]}>
|
||||||
{urls.map((url, idx) => (
|
{urls.map((url) => (
|
||||||
<Col span={8}>
|
<Col span={8}>
|
||||||
<VideoPlayer key={url} url={url} />
|
<VideoPlayer key={url} url={url} />
|
||||||
</Col>
|
</Col>
|
||||||
|
29
packages/meta/src/VideoPlayer/demo/newFlv.tsx
Normal file
29
packages/meta/src/VideoPlayer/demo/newFlv.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { Space, Button, VideoViewRef } from '@zhst/meta'
|
||||||
|
import { VIDEO_URL } from './mock'
|
||||||
|
import FlvPlayer from '../components/FlvPlayer/newFlvPlayer';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const videoRef = useRef<VideoViewRef>(null)
|
||||||
|
const [url] = useState(VIDEO_URL)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space direction='vertical'>
|
||||||
|
<Space>
|
||||||
|
<Button onClick={() => videoRef.current?.play()}>播放</Button>
|
||||||
|
</Space>
|
||||||
|
<div style={{ width: '800px' }}>
|
||||||
|
<FlvPlayer
|
||||||
|
ref={videoRef}
|
||||||
|
url={url}
|
||||||
|
config={{
|
||||||
|
enableStashBuffer: true,
|
||||||
|
stashInitialSize: 1024 * 700,
|
||||||
|
isLive: true,
|
||||||
|
hasVideo: true,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
@ -1,8 +1,6 @@
|
|||||||
.zhst-image__video-view {
|
.zhst-image__video-view {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
width: 100%;
|
|
||||||
height: 532px;
|
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
|
|
||||||
// &-flv {
|
// &-flv {
|
||||||
@ -37,7 +35,7 @@
|
|||||||
height: 32px;
|
height: 32px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 12px;
|
padding: 0 12px 0 24px;
|
||||||
background-color: rgb(0 0 0 / 80%);
|
background-color: rgb(0 0 0 / 80%);
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
|
|
||||||
|
@ -8,15 +8,30 @@ demo:
|
|||||||
cols: 2
|
cols: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
# VideoPlayer 视频播放
|
## VideoPlayer 视频播放
|
||||||
|
|
||||||
:::warning{title=注意}
|
:::warning{title=注意}
|
||||||
播放进度条操作还未完善,在播放结束和拖拽的过程中都有一定程度卡顿,目前逻辑待优化
|
播放进度条操作还未完善,在播放结束和拖拽的过程中都有一定程度卡顿,目前逻辑待优化
|
||||||
:::
|
:::
|
||||||
|
|
||||||
|
### 功能支持
|
||||||
|
|
||||||
|
1. 视频播放:mp4、ws链接、直播流... ✔
|
||||||
|
2. 视频操作:播放、暂停、全屏观看、进度条 ✔
|
||||||
|
3. 视频截图 ✔
|
||||||
|
4. 下载视频截图 ✔
|
||||||
|
5. OD 跟随
|
||||||
|
|
||||||
|
### 实现思路
|
||||||
|
|
||||||
|
#### OD 跟随
|
||||||
|
|
||||||
|
根据传递的od框数据实时跟踪目标移动轨迹,目前的构想是通过底层的flvjs拉取视频流播放,再通过canvas截帧,同时传入 OD 对象数组 requestAnimationFrame 去绘制;
|
||||||
|
|
||||||
<code src="./demo/basic.tsx">基础</code>
|
<code src="./demo/basic.tsx">基础</code>
|
||||||
|
|
||||||
<code src="./demo/multiple.tsx">测试视频播放压力</code>
|
<code src="./demo/multiple.tsx">测试视频播放压力</code>
|
||||||
|
<!-- <code src="./demo/newFlv.tsx" debug>新flv播放器</code> -->
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import download from "downloadjs";
|
||||||
|
|
||||||
export function getShowStatus(isLoadingVideo: boolean, isEnd: boolean, isError: boolean) {
|
export function getShowStatus(isLoadingVideo: boolean, isEnd: boolean, isError: boolean) {
|
||||||
let status = null;
|
let status = null;
|
||||||
@ -12,3 +13,44 @@ export function getShowStatus(isLoadingVideo: boolean, isEnd: boolean, isError:
|
|||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 下载功能的可配置属性
|
||||||
|
export interface DownloadFrameOptionProps {
|
||||||
|
fileName?: string; // 文件名称
|
||||||
|
downloadAble?: boolean; // 是否开启下载
|
||||||
|
fileType?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 视屏截帧、下载
|
||||||
|
export const downloadFrame = (_videoDom: HTMLVideoElement, opt?: DownloadFrameOptionProps) => {
|
||||||
|
const {
|
||||||
|
downloadAble = true,
|
||||||
|
fileName = 'image',
|
||||||
|
fileType = 'image/png'
|
||||||
|
} = opt || {}
|
||||||
|
try {
|
||||||
|
let video = _videoDom;
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
let base64;
|
||||||
|
|
||||||
|
//当视频处于还未加载出来时,截屏为黑色图片
|
||||||
|
if (video.readyState === 0) {
|
||||||
|
ctx?.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
canvas.width = video.offsetWidth;
|
||||||
|
canvas.height = video.offsetHeight;
|
||||||
|
// @ts-ignore
|
||||||
|
ctx.fillStyle = 'black';
|
||||||
|
ctx?.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
} else {
|
||||||
|
canvas.width = video.videoWidth;
|
||||||
|
canvas.height = video.videoHeight;
|
||||||
|
ctx?.drawImage(video, 0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
||||||
|
base64 = canvas.toDataURL(fileType);
|
||||||
|
downloadAble && download(base64, fileName);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -68,6 +68,7 @@ const CompareImage = forwardRef<AttachImageRefProps, AttachImageProps>((props) =
|
|||||||
<div className={classNames(`${componentName}-attach__scale`)}>
|
<div className={classNames(`${componentName}-attach__scale`)}>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
|
shape='circle'
|
||||||
//绝对定位下onClick事件失效采用onMouseDown
|
//绝对定位下onClick事件失效采用onMouseDown
|
||||||
onMouseDown={(e) => {
|
onMouseDown={(e) => {
|
||||||
//如果是左键执行
|
//如果是左键执行
|
||||||
@ -80,7 +81,7 @@ const CompareImage = forwardRef<AttachImageRefProps, AttachImageProps>((props) =
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
styles={{ display: 'flex' }}
|
color='#fff'
|
||||||
icon={isZoomin ? 'icon-cancle_fullscreen' : 'icon-fullscreen'}
|
icon={isZoomin ? 'icon-cancle_fullscreen' : 'icon-fullscreen'}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -7,13 +7,13 @@ export default () => {
|
|||||||
return (
|
return (
|
||||||
<Space>
|
<Space>
|
||||||
<div
|
<div
|
||||||
style={{ position: 'relative', width: '400px', height: '300px' }}
|
style={{ position: 'relative', width: '400px', height: '300px', border: '1px solid #ccc' }}
|
||||||
>
|
>
|
||||||
<AttachImage
|
<AttachImage
|
||||||
data={[
|
data={[
|
||||||
{
|
{
|
||||||
label: '人脸',
|
label: '人脸',
|
||||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'
|
url: 'http://jzx-drive.oss-cn-hangzhou.aliyuncs.com/note/2024/04/24/021337-image.png'
|
||||||
},
|
},
|
||||||
{label: '形体', url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'}
|
{label: '形体', url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png'}
|
||||||
]}
|
]}
|
||||||
|
@ -1,19 +1,21 @@
|
|||||||
.zhst-attach-image {
|
.zhst-attach-image {
|
||||||
position: relative;
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
|
pointer-events: none;
|
||||||
|
|
||||||
&-attach {
|
&-attach {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 11;
|
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
|
||||||
// left: 78px;
|
|
||||||
left: 0;
|
left: 0;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
|
pointer-events: auto;
|
||||||
|
|
||||||
|
|
||||||
&--zoomin {
|
&--zoomin {
|
||||||
@ -37,7 +39,7 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
transition: all 200ms;
|
transition: ease-out all 200ms;
|
||||||
|
|
||||||
&--select {
|
&--select {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
@ -57,11 +59,16 @@
|
|||||||
height: 30px;
|
height: 30px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background: rgb(0 0 0 / 60%);
|
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
background: rgb(0 0 0 / 30%);
|
||||||
|
transition: .3s ease-in all;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgb(0 0 0 / 5%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__img {
|
&__img {
|
||||||
|
@ -23,6 +23,7 @@ export interface CropperImageProps {
|
|||||||
lineConfig?: fabric.Line; // 线条配置
|
lineConfig?: fabric.Line; // 线条配置
|
||||||
editAble?: boolean; // 是否可编辑
|
editAble?: boolean; // 是否可编辑
|
||||||
selectedItem?: RectPro
|
selectedItem?: RectPro
|
||||||
|
selectAble?: boolean;
|
||||||
// 是否可放大缩小
|
// 是否可放大缩小
|
||||||
scaleAble?: boolean;
|
scaleAble?: boolean;
|
||||||
// 是否展示框选拓展框
|
// 是否展示框选拓展框
|
||||||
@ -77,6 +78,7 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
|
|||||||
onCropEnd,
|
onCropEnd,
|
||||||
editAble,
|
editAble,
|
||||||
onShapeSelected,
|
onShapeSelected,
|
||||||
|
selectAble = true,
|
||||||
showToast = false,
|
showToast = false,
|
||||||
customToast = () => <div>无</div>,
|
customToast = () => <div>无</div>,
|
||||||
type = 'ract',
|
type = 'ract',
|
||||||
@ -106,11 +108,12 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
|
|||||||
viewerRef.current = new Viewer(imageRef.current!!, {
|
viewerRef.current = new Viewer(imageRef.current!!, {
|
||||||
image: url,
|
image: url,
|
||||||
scaleAble,
|
scaleAble,
|
||||||
|
selectAble,
|
||||||
dragAble: false,
|
dragAble: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听形状选择事件
|
// 监听形状选择事件
|
||||||
addEventListenerWrapper(imageRef.current, EVENT_SHAPE_SELECT, async (e: { detail: any; }) => {
|
addEventListenerWrapper(imageRef.current, EVENT_SHAPE_SELECT, (e: { detail: any; }) => {
|
||||||
// 选中的od
|
// 选中的od
|
||||||
const id = e.detail;
|
const id = e.detail;
|
||||||
if (id) {
|
if (id) {
|
||||||
@ -156,7 +159,7 @@ const CropperImage = forwardRef<CropperImageRefProps, CropperImageProps>((props,
|
|||||||
onCropStart?.()
|
onCropStart?.()
|
||||||
});
|
});
|
||||||
// 矩形 - 结束绘制实践
|
// 矩形 - 结束绘制实践
|
||||||
cropEndRef.current = addEventListenerWrapper(imageRef.current, EVENT_CROP_END, async (event: { detail: any; }) => {
|
cropEndRef.current = addEventListenerWrapper(imageRef.current, EVENT_CROP_END, (event: { detail: any; }) => {
|
||||||
const data = event.detail;
|
const data = event.detail;
|
||||||
const imageRect = getImageDataByPosition({ x: data.left, y: data.top, w: data.width, h: data.height }, { canvas: viewerRef.current.canvas })
|
const imageRect = getImageDataByPosition({ x: data.left, y: data.top, w: data.width, h: data.height }, { canvas: viewerRef.current.canvas })
|
||||||
onCropEnd?.({ ...data , imageRect, targetTransform })
|
onCropEnd?.({ ...data , imageRect, targetTransform })
|
||||||
|
@ -1,5 +1,15 @@
|
|||||||
# @zhst/request
|
# @zhst/request
|
||||||
|
|
||||||
|
## 0.11.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- 视频添加 OD 框,查看大图首次点击修复
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
|
||||||
## 0.10.1
|
## 0.10.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
30
packages/request/es/index.d.ts
vendored
30
packages/request/es/index.d.ts
vendored
@ -1,30 +0,0 @@
|
|||||||
export interface ReqConfigProps {
|
|
||||||
timeout?: number;
|
|
||||||
baseURL?: string;
|
|
||||||
errorConfig?: {
|
|
||||||
errorHandler?: (error: any, opts: any) => void;
|
|
||||||
errorThrower?: (err: any) => void;
|
|
||||||
};
|
|
||||||
authorization?: string;
|
|
||||||
showMsg?: boolean;
|
|
||||||
onError: (error?: any) => void;
|
|
||||||
}
|
|
||||||
export declare const reqConfig: (config: ReqConfigProps) => {
|
|
||||||
timeout: number;
|
|
||||||
baseURL: string;
|
|
||||||
errorConfig: {
|
|
||||||
errorHandler?: ((error: any, opts: any) => void) | undefined;
|
|
||||||
errorThrower?: ((err: any) => void) | undefined;
|
|
||||||
};
|
|
||||||
authorization?: string | undefined;
|
|
||||||
showMsg?: boolean | undefined;
|
|
||||||
onError: (error?: any) => void;
|
|
||||||
requestInterceptors: (((url: any, options: any) => {
|
|
||||||
url: any;
|
|
||||||
options: any;
|
|
||||||
}) | ((error: any) => Promise<never>))[][];
|
|
||||||
responseInterceptors: ((response: {
|
|
||||||
status: number;
|
|
||||||
data: any;
|
|
||||||
}) => any)[][];
|
|
||||||
};
|
|
30
packages/request/lib/index.d.ts
vendored
30
packages/request/lib/index.d.ts
vendored
@ -1,30 +0,0 @@
|
|||||||
export interface ReqConfigProps {
|
|
||||||
timeout?: number;
|
|
||||||
baseURL?: string;
|
|
||||||
errorConfig?: {
|
|
||||||
errorHandler?: (error: any, opts: any) => void;
|
|
||||||
errorThrower?: (err: any) => void;
|
|
||||||
};
|
|
||||||
authorization?: string;
|
|
||||||
showMsg?: boolean;
|
|
||||||
onError: (error?: any) => void;
|
|
||||||
}
|
|
||||||
export declare const reqConfig: (config: ReqConfigProps) => {
|
|
||||||
timeout: number;
|
|
||||||
baseURL: string;
|
|
||||||
errorConfig: {
|
|
||||||
errorHandler?: ((error: any, opts: any) => void) | undefined;
|
|
||||||
errorThrower?: ((err: any) => void) | undefined;
|
|
||||||
};
|
|
||||||
authorization?: string | undefined;
|
|
||||||
showMsg?: boolean | undefined;
|
|
||||||
onError: (error?: any) => void;
|
|
||||||
requestInterceptors: (((url: any, options: any) => {
|
|
||||||
url: any;
|
|
||||||
options: any;
|
|
||||||
}) | ((error: any) => Promise<never>))[][];
|
|
||||||
responseInterceptors: ((response: {
|
|
||||||
status: number;
|
|
||||||
data: any;
|
|
||||||
}) => any)[][];
|
|
||||||
};
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/request",
|
"name": "@zhst/request",
|
||||||
"version": "0.10.1",
|
"version": "0.11.0",
|
||||||
"description": "请求库",
|
"description": "请求库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"request",
|
"request",
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# @zhst/slave
|
# @zhst/slave
|
||||||
|
|
||||||
|
## 0.6.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- @zhst/func@0.10.2
|
||||||
|
|
||||||
## 0.6.1
|
## 0.6.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@zhst/slave",
|
"name": "@zhst/slave",
|
||||||
"version": "0.6.1",
|
"version": "0.6.2",
|
||||||
"description": "微前端子应用方法库",
|
"description": "微前端子应用方法库",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"slave",
|
"slave",
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"@@/*": [".dumi/tmp/*"],
|
"@@/*": [".dumi/tmp/*"],
|
||||||
"@zhst/*": ["packages/*/src/"]
|
"@zhst/*": ["packages/*/src/"]
|
||||||
},
|
},
|
||||||
"importHelpers": true,
|
"importHelpers": false,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
|
Loading…
Reference in New Issue
Block a user