UNPKG

ui-picture-svg-marker

Version:

高仿百度AI图像物体检测标注控件,ui-picture-bd-marker SVG版

574 lines (526 loc) 24.6 kB
// MIT License // Copyright (c) 2020 FredDon // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. 'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _extends = Object.assign || 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; }; var _config = require('./config'); var _movement = require('./movement'); var _movement2 = _interopRequireDefault(_movement); var _ahaSvg = require('aha-svg'); var _ahaGraphic = require('aha-graphic'); var _drafthelper = require('./drafthelper'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var ResizeAnnotation = function ResizeAnnotation(parentNode, boundRect) { var _this = this; var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _config.defaultConfig; var callback_handler = arguments[3]; _classCallCheck(this, ResizeAnnotation); this._event = function () { if (_this.options.supportDelKey) { document.addEventListener("keydown", _this.delEvent); } else { document.removeEventListener("keydown", _this.delEvent); } }; this._uiconstruct = function () { if (_this.annotationContainer) { var imageOpContents = _this.annotationContainer.querySelectorAll('.' + _config.imageOpContent); for (var index = 0; index < imageOpContents.length; index++) { var opContent = imageOpContents[index]; if (!_this.options.showTags) { opContent.style.visibility = 'collapse'; } else { opContent.style.visibility = 'visible'; } if (_this.options.tagLocation == _config.defaultPositions.out_bottom) { opContent.style.position = 'absolute'; opContent.style.bottom = null; } else { opContent.style.position = null; } } } // if (_this.currentMovement && !_this.options.editable) { _this.currentMovement.moveNode.querySelectorAll('[class*=' + _config.PREFIX_RESIZE_DOT + ']').forEach(function (node) { if (node.classList.contains(_config.dotCls[8])) { node.classList.remove('hidden'); } else { node.classList.add('hidden'); } }); } }; this.setConfigOptions = function (newOptions) { _this.options = _extends({}, _this.options, newOptions.options); _this.rawConfig = _extends({}, _this.rawConfig, newOptions); _this._event(); _this._uiconstruct(); }; this.dataTemplate = function (tagObject, rRect) { if (!/^.+$/gi.test(tagObject.tag)) { tagObject.tag = 'temp@' + new Date().getTime(); } var shape = tagObject.shape; var position = null; if (shape == _config.supportShapes[0]) { var pRect = new _ahaGraphic.Rect(parseFloat(rRect.x), parseFloat(rRect.y), parseFloat(rRect.width), parseFloat(rRect.height)); var rectF = pRect.mapToRectF(); position = { x: rectF.left + "%", y: rectF.top + "%", x1: rectF.right + "%", y1: rectF.bottom + "%" }; } else if (shape == _config.supportShapes[1]) { position = { x: rRect.cx, y: rRect.cy, r: rRect.r }; } return _extends({}, tagObject, { position: position }); }; this.reset = function () { _this.data = []; }; this.isValid = function (rect) { return rect && (parseFloat(rect.width) > 1 && parseFloat(rect.height) > 1 || parseFloat(rect.r) > 1); }; this.renderData = function () { var dataArray = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; var base = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { width: _this.boundRect().width, height: _this.boundRect().height }; if (dataArray instanceof Array && dataArray.length > 0) { dataArray.forEach(function (data, index, arr) { var rect = void 0; if (data.position.x.endsWith('%')) { rect = { x: data.position.x, y: data.position.y, width: parseFloat(data.position.x1) - parseFloat(data.position.x) + '%', height: parseFloat(data.position.y1) - parseFloat(data.position.y) + '%' }; } else { rect = { x: (100 * data.position.x / base.width).toFixed(3) + '%', y: (100 * data.position.y / base.height).toFixed(3) + '%', width: (100 * (data.position.x1 - data.position.x) / base.width).toFixed(3) + '%', height: (100 * (data.position.y1 - data.position.y) / base.height).toFixed(3) + '%' }; } _this.drawAnnotation(rect, data, data.shape); }); } else { _this.reset(); } _this.rawConfig.onAnnoDataFullLoaded(); }; this.dataSource = function () { return _this.data; }; this.dataSourceOfTag = function (tagId, uuid) { for (var i = 0; i < _this.data.length; i++) { var value = _this.data[i]; if (value.tag === tagId && value.uuid == uuid) { return value; } } }; this.setTagForCurrentMovement = function (tagOb) { if (_this.currentMovement) { var node = _this.currentMovement.moveNode; var tag_str = '', tag_id = ''; if (typeof tagOb === 'string') { tag_id = tag_str = tagOb; } var oldtag = node.dataset.id; var constData = {}; if ((typeof tagOb === 'undefined' ? 'undefined' : _typeof(tagOb)) === 'object') { tag_str = tagOb['tagName']; tag_id = tagOb['tag']; constData = _extends({}, tagOb); } var uuid = node.dataset.uuid; //svg has no `innerText` node.querySelector('.' + _config.imageOpTag).innerHTML = tag_str; for (var i = 0; i < _this.data.length; i++) { var value = _this.data[i]; var oldValue = Object.assign({}, value); if (value.tag === oldtag && value.uuid === uuid) { value = _extends({}, value, constData, { tag: tag_id, tagName: tag_str }); node.dataset.id = tag_id; node.dataset.name = tag_str; _this.rawConfig.onAnnoChanged(value, oldValue); _this.data[i] = value; } } _this.rawConfig.onUpdated(_this.dataSource()); } }; this.updateMovementData = function () { //获取tag if (_this.currentMovement == null) return; var node = _this.currentMovement.moveNode; var uuid = node.dataset.uuid; // querySelector(`.${imageOpTag}`) var tag = node.dataset.id; var mainElement = node.firstElementChild; //从原有的数据集查找该tag var changed = false; for (var i = 0; i < _this.data.length; i++) { var value = _this.data[i]; var oldValue = Object.assign({}, value); if (value.tag === tag && value.uuid === uuid) { var position = (0, _drafthelper.getFrameData)(mainElement, value.shape); if (JSON.stringify(value.position) != JSON.stringify(position)) { value.position = position; _this.data[i] = value; changed = true; _this.rawConfig.onAnnoChanged(value, oldValue); } break; } } if (changed) { _this.rawConfig.onUpdated(_this.dataSource(), _this.currentMovement); } }; this._removeAnnotationEvent = function (e) { if (!_this.options.editable) return; var selectNode = e.currentTarget.parentNode.parentNode.parentNode; _this.removeAnnotation(selectNode); }; this.removeAnnotation = function (node) { if (node) { var uuid = node.dataset.uuid; // const tag = node.querySelector(`.${imageOpTag}`).dataset.id; var value = void 0; for (var i = 0; i < _this.data.length; i++) { value = _this.data[i]; if ( //value.tag === tag && value.uuid === uuid) { if (_this.rawConfig.onAnnoRemoved(value)) { _this.data.splice(i, 1); } break; } } _this.rawConfig.onUpdated(_this.dataSource()); node.remove(); } }; this.drawAnnotation = function (rRect) { var tag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : void 0; var shape = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "rect"; // debugger if (!_this.isValid(rRect)) { return; } _this.removeSelectedAnnotation(); //创建Annotation节点 // annotationContainer //边框 var rr = _this.boundRect(); //region var collectionArr = []; var rectStr = (0, _drafthelper.getShapeAnnoSVGString)(rRect, _this.options.annotationClass + ' selected', shape); collectionArr.push(rectStr); // let rSize = { // x: isNaN(rRect.x) ? parseFloat(rRect.x) * 0.01 * rRect.width : rRect.x, // y: isNaN(rRect.y) ? parseFloat(rRect.y) * 0.01 * rRect.height : rRect.y, // height: rr.height * 0.01 * parseFloat(rRect.height), // width: rr.width * 0.01 * parseFloat(rRect.width), // } var uu = '' + (0, _config.UUID)(16, 16); var tagString = void 0, tagId = void 0; if ((typeof tag === 'undefined' ? 'undefined' : _typeof(tag)) === 'object') { tagString = tag.tagName; tagId = tag.tag; } else if (typeof tag === 'string') { tagString = tag; tagId = tag; } else { tagString = '请选择或添加新标签'; tagId = 'temp@' + uu; } tag = _extends({}, tag, { tag: tagId, tagName: tagString, shape: shape }); var pRect = new _ahaGraphic.Rect(parseFloat(rRect.x), parseFloat(rRect.y), parseFloat(rRect.width), parseFloat(rRect.height)); var arr = (0, _drafthelper.resizeDotPoints)({ tagId: tagId, tagString: tagString }, rRect, rr, shape, _this.options); collectionArr.push.apply(collectionArr, _toConsumableArray(arr)); var annotation = (0, _ahaSvg.toElement)('<g>' + collectionArr.join('') + '</g>'); //group if (annotation) { var del = annotation.querySelector('.g-image-op-del'); if (del) { del.addEventListener('click', _this._removeAnnotationEvent, true); } } else { return; } annotation.dataset.shape = shape; annotation.dataset.uuid = uu; annotation.dataset.id = tagId; _this.annotationContainer.appendChild(annotation); // for (let prop in resizeDotClasses) { // let resizeDot = document.createElement('div'); // if (i === 8) { // resizeDot.className = `${this.options.blurOtherDotsShowTags // ? '' // : `${dotCls[i]}`} ${resizeDotClasses[prop]}`; // let opContent = document.createElement('div'); // opContent.className = imageOpContent; // if (!this.options.showTags) { // opContent.style.visibility = 'collapse'; // } else { // opContent.style.visibility = 'visible'; // } // if (this.options.tagLocation == defaultPositions.out_bottom) { // opContent.style.position = 'absolute'; // opContent.style.bottom = null; // } else { // opContent.style.position = null; // } // let trash = document.createElement('i'); // trash.className = 'g-image-op-del iconfont s-icon icon-trash s-icon-trash'; // trash.innerText = ' × '; // trash.addEventListener('click', this._removeAnnotationEvent, true); // let tag = document.createElement('span'); // tag.dataset.name = tagString; // tag.className = `${imageOpTag}`; // tag.innerText = tagString; // tag.dataset.id = tagId; // if (this.options.trashPositionStart) { // opContent.appendChild(trash); // opContent.appendChild(tag); // } else { // opContent.appendChild(tag); // opContent.appendChild(trash); // } // resizeDot.appendChild(opContent); // } else { // resizeDot.className = `${resizeDotClasses[prop]} ${dotCls[i]} ${this.options.editable // ? '' // : 'hidden'}`; // } // annotation.appendChild(resizeDot); // i++; // } // //加事件 annotation.oncontextmenu = function (e) { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); var node = e.currentTarget; var tagAttr = node.querySelector('.' + _config.imageOpTag).dataset; var ab = _this.dataSourceOfTag(tagAttr.id, node.dataset.uuid); _this.rawConfig.onAnnoContextMenu(ab, node, _this); // this.removeAnnotation(node); return true; }; _this.currentMovement = new _movement2.default(annotation, 0, _this.boundRect(), _this.options); // this.selectAnnotation(); var dts = _this.dataTemplate(tag, rRect); var insertItem = _extends({}, dts, { uuid: uu }); _this.data.push(insertItem); _this.rawConfig.onAnnoAdded(insertItem, annotation); _this.rawConfig.onUpdated(_this.dataSource()); }; this.dragEventOn = function (e) { // e.preventDefault(); // e.stopPropagation(); // if (!e.target.classList.contains('annotation') && // !e.target.classList.contains(`${PREFIX_RESIZE_DOT}`)) { // eventTargetOnTransform = false; // } var eventType = e.type; // console.log(`eventType=${eventType}`); if (eventType === _config.MOUSE_EVENT[6]) { _this.selectAnnotation(); return; } var clientX = e.clientX, clientY = e.clientY; if (e.targetTouches && e.targetTouches.length > 0) { var touch = e.targetTouches[0]; clientX = touch ? touch.clientX : undefined; clientY = touch ? touch.clientY : undefined; } _this.moveX = clientX; //- this.boundRect().x; _this.moveY = clientY; //- this.boundRect().y; if (eventType === _config.MOUSE_EVENT[0] || eventType === _config.TOUCH_EVENT[0]) { _this.actionDown = true; _this.lastX = _this.moveX; _this.lastY = _this.moveY; if (typeof _this.callback_handler === 'function') { _this.callback_handler(true); } // eventTargetOnTransform = true; _this.targetEventType(e); } else if (eventType === _config.MOUSE_EVENT[1] || eventType === _config.MOUSE_EVENT[3] || eventType === _config.MOUSE_EVENT[5] || eventType === _config.TOUCH_EVENT[1] || eventType === _config.TOUCH_EVENT[3] || eventType === _config.TOUCH_EVENT[5]) { if (_this.currentMovement == null) { return true; } if (_this.actionDown) { if (_this.filterOutOfBounds(_this.moveX, _this.moveY)) { return; } _this.currentMovement.transform(_this.moveX - _this.lastX, _this.moveY - _this.lastY); _this.lastX = _this.moveX; _this.lastY = _this.moveY; } } else { if (typeof _this.callback_handler === 'function') { _this.callback_handler(false); } // eventTargetOnTransform = false; if (_this.actionDown) { _this.updateMovementData(); _this.selectAnnotation(); } _this.actionDown = false; } }; this.removeSelectedAnnotation = function () { if (_this.currentMovement) { var cs = _this.currentMovement.moveNode.classList; cs.remove('selected'); if (_this.options.blurOtherDots) { _this.currentMovement.moveNode.querySelectorAll('[class*=' + _config.PREFIX_RESIZE_DOT + ']').forEach(function (node) { if (node.classList.contains(_config.dotCls[8])) {} else { node.classList.add('hidden'); } }); } // fix unselect mv can be deleted _this.currentMovement = null; } }; this.selectAnnotation = function () { var isUserinteracted = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; if (_this.currentMovement) { var cs = _this.currentMovement.moveNode.classList; cs.add('selected'); if (_this.options.blurOtherDots) { if (!_this.options.editable) { _this.currentMovement.moveNode.querySelectorAll('[class*=' + _config.PREFIX_RESIZE_DOT + ']').forEach(function (node) { if (node.classList.contains(_config.dotCls[8])) { node.classList.remove('hidden'); } else { node.classList.add('hidden'); } }); return; } _this.currentMovement.moveNode.querySelectorAll('[class*=' + _config.PREFIX_RESIZE_DOT + ']').forEach(function (node) { node.classList.remove('hidden'); }); } if (!isUserinteracted) return; var node = _this.currentMovement.moveNode; // const tag_str = node.querySelector(`.${imageOpTag}`).innerText; var tagAttr = node.dataset; var selectData = _extends({}, tagAttr, _this.dataSourceOfTag(tagAttr.id, tagAttr.uuid)); _this.rawConfig.onAnnoSelected(selectData, node); } }; this.selectMarkerByTagId = function (tagId) { var tag = _this.annotationContainer.querySelector('[data-id="' + tagId + '"]'); if (tag) { var markerAnnotation = tag.parentNode.parentNode.parentNode; _this.removeSelectedAnnotation(); _this.currentMovement = new _movement2.default(markerAnnotation, -1, _this.boundRect(), _this.options); _this.selectAnnotation(false); } }; this.targetEventType = function (e) { _this.removeSelectedAnnotation(); var el = e.target; var parentEl = el.classList.contains('annotation') ? el.parentNode : el.parentNode; if (el.classList.contains(_config.dotCls[0])) { //top _this.currentMovement = new _movement2.default(parentEl, 0, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[1])) { //bottom _this.currentMovement = new _movement2.default(parentEl, 1, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[2])) { //left _this.currentMovement = new _movement2.default(parentEl, 2, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[3])) { //right _this.currentMovement = new _movement2.default(parentEl, 3, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[4])) { //top-left _this.currentMovement = new _movement2.default(parentEl, 4, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[5])) { //top-right _this.currentMovement = new _movement2.default(parentEl, 5, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[6])) { //bottom-left _this.currentMovement = new _movement2.default(parentEl, 6, _this.boundRect(), _this.options); } else if (el.classList.contains(_config.dotCls[7])) { //bottom-right _this.currentMovement = new _movement2.default(parentEl, 7, _this.boundRect(), _this.options); } else if (el.classList.contains('annotation')) { _this.currentMovement = new _movement2.default(parentEl, -1, _this.boundRect(), _this.options); } else { _this.currentMovement = null; } // this.selectAnnotation(); }; this.filterOutOfBounds = function (x, y) { return x >= _this.boundRect().x + _this.boundRect().width + 2 || y >= _this.boundRect().y + _this.boundRect().height + 2 || x < 5 || y < 5; }; this.options = _extends({}, _config.defaultConfig.options); this.currentShape = ''; this.rawConfig = _extends({}, _config.defaultConfig); this.callback_handler = callback_handler; this.annotationContainer = parentNode; this.boundRect = boundRect; this.actionDown = false; this.currentMovement = null; this.data = []; var that = this; this.delEvent = function (e) { if (e.keyCode === 8 || e.keyCode === 46) { var currentMovement = that.currentMovement; if (currentMovement) { that.removeAnnotation(currentMovement.moveNode); } } }; this.setConfigOptions(callback); } //获取数据模板 //init ; exports.default = ResizeAnnotation;