mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
add ui
This commit is contained in:
1 parent
777a4bc927
commit
9c45527522
396 files changed
+13772
No files matched your search
@@ -0,0 +1,193 @@
|
||||
import _ from 'lodash';
|
||||
import delay from 'vj/utils/delay';
|
||||
import Tooltip from 'vj/components/tooltip/Tooltip';
|
||||
import i18n from 'vj/utils/i18n';
|
||||
|
||||
const MARKER_ID = `marker_${Math.floor(Math.random() * 0xFFFFFF).toString(16)}`;
|
||||
const MARKER_OFFSET = 20;
|
||||
const MARKER_MAX_DISTANCE = 60;
|
||||
|
||||
let markerInstance = null;
|
||||
|
||||
function distanceToRect(px, py, rect) {
|
||||
const cx = (rect.left + rect.right) / 2;
|
||||
const cy = (rect.top + rect.bottom) / 2;
|
||||
const dx = Math.max(Math.abs(px - cx) - (rect.right - rect.left) / 2, 0);
|
||||
const dy = Math.max(Math.abs(py - cy) - (rect.bottom - rect.top) / 2, 0);
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
class Marker {
|
||||
static exists() {
|
||||
return markerInstance && document.getElementById(MARKER_ID);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
if (Marker.exists()) {
|
||||
return markerInstance;
|
||||
}
|
||||
if (markerInstance) {
|
||||
markerInstance.destroy();
|
||||
}
|
||||
this.$dom = $(`
|
||||
<div class="marker" id="${MARKER_ID}"><div class="marker__toolbar">
|
||||
<div class="marker__action" data-color="#ffff00" data-tooltip="${i18n('Mark Yellow')}"><span class="marker__icon icon-yellow"></span></div>
|
||||
<div class="marker__action" data-color="#47ff6f" data-tooltip="${i18n('Mark Green')}"><span class="marker__icon icon-green"></span></div>
|
||||
<div class="marker__action" data-color="transparent" data-tooltip="${i18n('Clear Marks')}"><span class="icon icon-erase"></span></div>
|
||||
</div></div>
|
||||
`)
|
||||
.appendTo('body');
|
||||
this.$dom.find('.marker__toolbar').on('click', '.marker__action', this.onMarkerActionClick.bind(this));
|
||||
this.$dom.on('mousedown', this.onMarkerMouseDown.bind(this));
|
||||
this.isOpen = false;
|
||||
this.bindedHandlers = false;
|
||||
this._onKeyDown = this.onKeyDown.bind(this);
|
||||
this._onScroll = _.throttle(this.onScroll.bind(this), 50);
|
||||
this._onMouseDown = this.onMouseDown.bind(this);
|
||||
this._onMouseMove = _.throttle(this.onMouseMove.bind(this), 50);
|
||||
markerInstance = this;
|
||||
}
|
||||
|
||||
markSelection(color) {
|
||||
const selection = window.getSelection();
|
||||
const range = selection.getRangeAt(0);
|
||||
this.$container.attr('contentEditable', true);
|
||||
if (range) {
|
||||
// recover ranges
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
if (!document.execCommand('HiliteColor', false, color)) {
|
||||
document.execCommand('BackColor', false, color);
|
||||
}
|
||||
this.$container.removeAttr('contentEditable');
|
||||
if (range) {
|
||||
// remove ranges after marking
|
||||
selection.removeAllRanges();
|
||||
}
|
||||
}
|
||||
|
||||
showAtPosition($container, x, y) {
|
||||
this.$container = $container;
|
||||
this.$dom.css({
|
||||
display: 'block',
|
||||
opacity: 0,
|
||||
});
|
||||
const rect = this.$dom[0].getBoundingClientRect();
|
||||
this.$dom.css({
|
||||
left: x + MARKER_OFFSET,
|
||||
top: y - (rect.bottom - rect.top) - MARKER_OFFSET,
|
||||
});
|
||||
this.isOpen = true;
|
||||
this.$dom.addClass('open');
|
||||
this.updateMarkerOpacity(x, y);
|
||||
this.bindEventHandlersForClosing();
|
||||
}
|
||||
|
||||
async close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
this.isOpen = false;
|
||||
this.closeTooltipsImmediately();
|
||||
this.unbindEventHandlers();
|
||||
this.$dom
|
||||
.css({ opacity: 0 })
|
||||
.removeClass('open');
|
||||
await delay(200);
|
||||
if (!this.isOpen) {
|
||||
this.$dom.hide();
|
||||
}
|
||||
}
|
||||
|
||||
closeTooltipsImmediately() {
|
||||
const $elements = this.$dom.find('[data-tooltip]');
|
||||
$elements.get().forEach((element) => {
|
||||
const $el = $(element);
|
||||
const tooltipInstance = Tooltip.get($el);
|
||||
if (tooltipInstance) {
|
||||
tooltipInstance.detach();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bindEventHandlersForClosing() {
|
||||
if (this.bindedHandlers) {
|
||||
return;
|
||||
}
|
||||
$(document).on('keydown', this._onKeyDown);
|
||||
$(window).on('scroll', this._onScroll);
|
||||
$(document).on('mousedown', this._onMouseDown);
|
||||
$(document).on('mousemove', this._onMouseMove);
|
||||
this.bindedHandlers = true;
|
||||
}
|
||||
|
||||
unbindEventHandlers() {
|
||||
if (!this.bindedHandlers) {
|
||||
return;
|
||||
}
|
||||
$(document).off('keydown', this._onKeyDown);
|
||||
$(window).off('scroll', this._onScroll);
|
||||
$(document).off('mousedown', this._onMouseDown);
|
||||
$(document).off('mousemove', this._onMouseMove);
|
||||
this.bindedHandlers = false;
|
||||
}
|
||||
|
||||
onMarkerActionClick(ev) {
|
||||
const color = $(ev.currentTarget).attr('data-color');
|
||||
this.markSelection(color);
|
||||
this.close();
|
||||
}
|
||||
|
||||
onMarkerMouseDown(ev) {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
onKeyDown() {
|
||||
this.close();
|
||||
}
|
||||
|
||||
onScroll() {
|
||||
this.close();
|
||||
}
|
||||
|
||||
onMouseMove(ev) {
|
||||
this.updateMarkerOpacity(ev.clientX, ev.clientY);
|
||||
}
|
||||
|
||||
onMouseDown() {
|
||||
this.close();
|
||||
}
|
||||
|
||||
updateMarkerOpacity(x, y) {
|
||||
const markerRect = this.$dom[0].getBoundingClientRect();
|
||||
const distance = distanceToRect(x, y, markerRect);
|
||||
if (distance > MARKER_MAX_DISTANCE) {
|
||||
this.close();
|
||||
return;
|
||||
}
|
||||
this.$dom.css('opacity', 1 - (distance / MARKER_MAX_DISTANCE));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.close();
|
||||
this.$dom.remove();
|
||||
markerInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
const MarkerInterface = {
|
||||
close() {
|
||||
if (!markerInstance) {
|
||||
return;
|
||||
}
|
||||
markerInstance.close();
|
||||
},
|
||||
showAtPosition($container, x, y) {
|
||||
const marker = new Marker();
|
||||
marker.showAtPosition($container, x, y);
|
||||
},
|
||||
};
|
||||
|
||||
export default MarkerInterface;
|
||||
Reference in new issue
Block a user