mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-02-07 14:18:21 +00:00
fix outlines
This commit is contained in:
parent
4d4cfab271
commit
a56faac6ae
@ -72,10 +72,12 @@ export class OutlineHovering extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const host = this.context as SimulatorHost;
|
const host = this.context as SimulatorHost;
|
||||||
const current = this.current;
|
const current = this.current;
|
||||||
if (!current) {
|
console.info('current', current)
|
||||||
|
if (!current || host.viewport.scrolling) {
|
||||||
return <Fragment />;
|
return <Fragment />;
|
||||||
}
|
}
|
||||||
const instances = host.getComponentInstances(current);
|
const instances = host.getComponentInstances(current);
|
||||||
|
console.info('current instances', instances)
|
||||||
if (!instances || instances.length < 1) {
|
if (!instances || instances.length < 1) {
|
||||||
return <Fragment />;
|
return <Fragment />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { SimulatorContext } from '../context';
|
|||||||
import { SimulatorHost } from '../host';
|
import { SimulatorHost } from '../host';
|
||||||
import { computed } from '@recore/obx';
|
import { computed } from '@recore/obx';
|
||||||
import OffsetObserver from '../../../../designer/helper/offset-observer';
|
import OffsetObserver from '../../../../designer/helper/offset-observer';
|
||||||
|
import Node from '../../../../designer/document/node/node';
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class OutlineSelectingInstance extends Component<{ observed: OffsetObserver; highlight?: boolean }> {
|
export class OutlineSelectingInstance extends Component<{ observed: OffsetObserver; highlight?: boolean }> {
|
||||||
@ -12,18 +13,22 @@ export class OutlineSelectingInstance extends Component<{ observed: OffsetObserv
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.observed.purge();
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { observed, highlight } = this.props;
|
const { observed, highlight } = this.props;
|
||||||
if (!observed.hasOffset) {
|
if (!observed.hasOffset) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { scale, width, height, offsetTop, offsetLeft } = observed;
|
const { offsetWidth, offsetHeight, offsetTop, offsetLeft } = observed;
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
width: width * scale,
|
width: offsetWidth,
|
||||||
height: height * scale,
|
height: offsetHeight,
|
||||||
transform: `translate3d(${offsetLeft * scale}px, ${offsetTop * scale}px, 0)`,
|
transform: `translate3d(${offsetLeft}px, ${offsetTop}px, 0)`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const className = classNames('lc-outlines lc-outlines-selecting', {
|
const className = classNames('lc-outlines lc-outlines-selecting', {
|
||||||
@ -39,13 +44,54 @@ export class OutlineSelectingInstance extends Component<{ observed: OffsetObserv
|
|||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class OutlineSelecting extends Component {
|
export class OutlineSelectingForNode extends Component<{ node: Node }> {
|
||||||
static contextType = SimulatorContext;
|
static contextType = SimulatorContext;
|
||||||
|
|
||||||
|
get host(): SimulatorHost {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get instances() {
|
||||||
|
return this.host.getComponentInstances(this.props.node);
|
||||||
|
}
|
||||||
|
|
||||||
shouldComponentUpdate() {
|
shouldComponentUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { instances } = this;
|
||||||
|
const { node } = this.props;
|
||||||
|
const designer = this.host.designer;
|
||||||
|
|
||||||
|
if (!instances || instances.length < 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Fragment key={node.id}>
|
||||||
|
{instances.map((instance) => {
|
||||||
|
const observed = designer.createOffsetObserver({
|
||||||
|
node,
|
||||||
|
instance,
|
||||||
|
});
|
||||||
|
if (!observed) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return <OutlineSelectingInstance key={observed.id} observed={observed} />;
|
||||||
|
})}
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@observer
|
||||||
|
export class OutlineSelecting extends Component {
|
||||||
|
static contextType = SimulatorContext;
|
||||||
|
|
||||||
|
get host(): SimulatorHost {
|
||||||
|
return this.context;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get selecting() {
|
@computed get selecting() {
|
||||||
const doc = this.host.document;
|
const doc = this.host.document;
|
||||||
if (doc.suspensed) {
|
if (doc.suspensed) {
|
||||||
@ -54,8 +100,8 @@ export class OutlineSelecting extends Component {
|
|||||||
return doc.selection.getNodes();
|
return doc.selection.getNodes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get host(): SimulatorHost {
|
shouldComponentUpdate() {
|
||||||
return this.context;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -65,30 +111,11 @@ export class OutlineSelecting extends Component {
|
|||||||
return <Fragment />;
|
return <Fragment />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const designer = this.host.designer;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{selecting.map(node => {
|
{selecting.map(node => (
|
||||||
const instances = this.host.getComponentInstances(node);
|
<OutlineSelectingForNode key={node.id} node={node} />
|
||||||
if (!instances || instances.length < 1) {
|
))}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Fragment key={node.id}>
|
|
||||||
{instances.map((instance, i) => {
|
|
||||||
const observed = designer.createOffsetObserver({
|
|
||||||
node,
|
|
||||||
instance,
|
|
||||||
});
|
|
||||||
if (!observed) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <OutlineSelectingInstance key={`line-s-${i}`} observed={observed} />;
|
|
||||||
})}
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import {
|
|||||||
DragNodeDataObject,
|
DragNodeDataObject,
|
||||||
isDragAnyObject,
|
isDragAnyObject,
|
||||||
isDragNodeObject,
|
isDragNodeObject,
|
||||||
|
isDragNodeDataObject,
|
||||||
} from '../../../designer/helper/dragon';
|
} from '../../../designer/helper/dragon';
|
||||||
import {
|
import {
|
||||||
LocationData,
|
LocationData,
|
||||||
@ -347,11 +348,20 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@obx.val private instancesMap = new Map<string, ReactInstance[]>();
|
||||||
|
setInstance(id: string, instances: ReactInstance[] | null) {
|
||||||
|
if (instances == null) {
|
||||||
|
this.instancesMap.delete(id);
|
||||||
|
} else {
|
||||||
|
this.instancesMap.set(id, instances.slice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ISimulator
|
* @see ISimulator
|
||||||
*/
|
*/
|
||||||
getComponentInstances(node: Node): ReactInstance[] | null {
|
getComponentInstances(node: Node): ReactInstance[] | null {
|
||||||
return this._renderer?.getComponentInstances(node.id) || null;
|
return this.instancesMap.get(node.id) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -888,12 +898,22 @@ export class SimulatorHost implements ISimulator<SimulatorProps> {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
checkNesting(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
|
checkNesting(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
|
||||||
const items: Array<Node | NodeSchema> = dragObject.nodes || (dragObject as DragNodeDataObject).data;
|
let items: Array<Node | NodeSchema>;
|
||||||
|
if (isDragNodeDataObject(dragObject)) {
|
||||||
|
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
|
||||||
|
} else {
|
||||||
|
items = dragObject.nodes
|
||||||
|
}
|
||||||
return items.every(item => this.checkNestingDown(dropTarget, item));
|
return items.every(item => this.checkNestingDown(dropTarget, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDropTarget(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
|
checkDropTarget(dropTarget: NodeParent, dragObject: DragNodeObject | DragNodeDataObject): boolean {
|
||||||
const items: Array<Node | NodeSchema> = dragObject.nodes || (dragObject as DragNodeDataObject).data;
|
let items: Array<Node | NodeSchema>;
|
||||||
|
if (isDragNodeDataObject(dragObject)) {
|
||||||
|
items = Array.isArray(dragObject.data) ? dragObject.data : [dragObject.data];
|
||||||
|
} else {
|
||||||
|
items = dragObject.nodes
|
||||||
|
}
|
||||||
return items.every(item => this.checkNestingUp(dropTarget, item));
|
return items.every(item => this.checkNestingUp(dropTarget, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -98,14 +98,28 @@ export default class Viewport implements IViewport {
|
|||||||
return this._scrollTarget;
|
return this._scrollTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@obx private _scrolling: boolean = false;
|
||||||
|
get scrolling(): boolean {
|
||||||
|
return this._scrolling;
|
||||||
|
}
|
||||||
|
|
||||||
setScrollTarget(target: Window) {
|
setScrollTarget(target: Window) {
|
||||||
const scrollTarget = new ScrollTarget(target);
|
const scrollTarget = new ScrollTarget(target);
|
||||||
this._scrollX = scrollTarget.left;
|
this._scrollX = scrollTarget.left;
|
||||||
this._scrollY = scrollTarget.top;
|
this._scrollY = scrollTarget.top;
|
||||||
target.onscroll = () => {
|
|
||||||
|
let scrollTimer: any;
|
||||||
|
target.addEventListener('scroll', () => {
|
||||||
this._scrollX = scrollTarget.left;
|
this._scrollX = scrollTarget.left;
|
||||||
this._scrollY = scrollTarget.top;
|
this._scrollY = scrollTarget.top;
|
||||||
};
|
this._scrolling = true;
|
||||||
|
if (scrollTimer) {
|
||||||
|
clearTimeout(scrollTimer);
|
||||||
|
}
|
||||||
|
scrollTimer = setTimeout(() => {
|
||||||
|
this._scrolling = false;
|
||||||
|
}, 80);
|
||||||
|
});
|
||||||
this._scrollTarget = scrollTarget;
|
this._scrollTarget = scrollTarget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,10 +40,11 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
|||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { renderer } = this.props;
|
const { renderer } = this.props;
|
||||||
|
const { components, schemas } = LowCodeRenderer.others
|
||||||
return (
|
return (
|
||||||
<LowCodeRenderer
|
<LowCodeRenderer
|
||||||
schema={renderer.schema}
|
schema={renderer.schema}
|
||||||
components={renderer.components}
|
components={components /*renderer.components*/}
|
||||||
appHelper={renderer.context}
|
appHelper={renderer.context}
|
||||||
// context={renderer.context}
|
// context={renderer.context}
|
||||||
designMode={renderer.designMode}
|
designMode={renderer.designMode}
|
||||||
@ -60,11 +61,3 @@ class Renderer extends Component<{ renderer: SimulatorRenderer }> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
class LowCodeRenderer extends Component<any> {
|
|
||||||
render() {
|
|
||||||
const { schema } = this.props;
|
|
||||||
return <div>{JSON.stringify(this.props.schema)}</div>
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|||||||
@ -99,7 +99,18 @@ export class SimulatorRenderer {
|
|||||||
load(asset: Asset): Promise<any> {
|
load(asset: Asset): Promise<any> {
|
||||||
return loader.load(asset);
|
return loader.load(asset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private instancesMap = new Map<string, ReactInstance[]>();
|
private instancesMap = new Map<string, ReactInstance[]>();
|
||||||
|
private unmountIntance(id: string, instance: ReactInstance) {
|
||||||
|
const instances = this.instancesMap.get(id);
|
||||||
|
if (instances) {
|
||||||
|
const i = instances.indexOf(instance);
|
||||||
|
if (i > -1) {
|
||||||
|
instances.splice(i, 1);
|
||||||
|
host.setInstance(id, instances);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
mountInstance(id: string, instance: ReactInstance | null) {
|
mountInstance(id: string, instance: ReactInstance | null) {
|
||||||
const instancesMap = this.instancesMap;
|
const instancesMap = this.instancesMap;
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
@ -108,41 +119,57 @@ export class SimulatorRenderer {
|
|||||||
instances = instances.filter(checkInstanceMounted);
|
instances = instances.filter(checkInstanceMounted);
|
||||||
if (instances.length > 0) {
|
if (instances.length > 0) {
|
||||||
instancesMap.set(id, instances);
|
instancesMap.set(id, instances);
|
||||||
|
host.setInstance(id, instances);
|
||||||
} else {
|
} else {
|
||||||
instancesMap.delete(id);
|
instancesMap.delete(id);
|
||||||
|
host.setInstance(id, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const unmountIntance = this.unmountIntance.bind(this);
|
||||||
|
const origId = (instance as any)[SYMBOL_VNID];
|
||||||
|
if (origId && origId !== id) {
|
||||||
|
// 另外一个节点的 instance 在此被复用了,需要从原来地方卸载
|
||||||
|
unmountIntance(origId, instance);
|
||||||
|
}
|
||||||
if (isElement(instance)) {
|
if (isElement(instance)) {
|
||||||
cacheReactKey(instance);
|
cacheReactKey(instance);
|
||||||
} else if (!(instance as any)[SYMBOL_VNID]) {
|
} else if (origId !== id) {
|
||||||
const origUnmout = instance.componentWillUnmount;
|
// 涵盖 origId == null || origId !== id 的情况
|
||||||
|
let origUnmount: any = instance.componentWillUnmount;
|
||||||
|
if (origUnmount && origUnmount.origUnmount) {
|
||||||
|
origUnmount = origUnmount.origUnmount;
|
||||||
|
}
|
||||||
// hack! delete instance from map
|
// hack! delete instance from map
|
||||||
instance.componentWillUnmount = function() {
|
const newUnmount = function (this: any) {
|
||||||
const instances = instancesMap.get(id);
|
unmountIntance(id, instance);
|
||||||
if (instances) {
|
origUnmount && origUnmount.call(this);
|
||||||
const i = instances.indexOf(instance);
|
|
||||||
if (i > -1) {
|
|
||||||
instances.splice(i, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
origUnmout && origUnmout.call(this);
|
|
||||||
};
|
};
|
||||||
|
(newUnmount as any).origUnmount = origUnmount;
|
||||||
|
instance.componentWillUnmount = newUnmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
(instance as any)[SYMBOL_VNID] = id;
|
(instance as any)[SYMBOL_VNID] = id;
|
||||||
let instances = this.instancesMap.get(id);
|
let instances = this.instancesMap.get(id);
|
||||||
if (instances) {
|
if (instances) {
|
||||||
|
const l = instances.length;
|
||||||
instances = instances.filter(checkInstanceMounted);
|
instances = instances.filter(checkInstanceMounted);
|
||||||
|
let updated = instances.length !== l;
|
||||||
if (!instances.includes(instance)) {
|
if (!instances.includes(instance)) {
|
||||||
instances.push(instance);
|
instances.push(instance);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (!updated) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
instancesMap.set(id, instances);
|
|
||||||
} else {
|
} else {
|
||||||
instancesMap.set(id, [instance]);
|
instances = [instance];
|
||||||
}
|
}
|
||||||
|
instancesMap.set(id, instances);
|
||||||
|
host.setInstance(id, instances);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ctxMap = new Map<string, object>();
|
private ctxMap = new Map<string, object>();
|
||||||
mountContext(id: string, ctx: object) {
|
mountContext(id: string, ctx: object) {
|
||||||
this.ctxMap.set(id, ctx);
|
this.ctxMap.set(id, ctx);
|
||||||
@ -167,21 +194,12 @@ export class SimulatorRenderer {
|
|||||||
setNativeSelection(enableFlag: boolean) {
|
setNativeSelection(enableFlag: boolean) {
|
||||||
setNativeSelection(enableFlag);
|
setNativeSelection(enableFlag);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @see ISimulator
|
|
||||||
*/
|
|
||||||
setDraggingState(state: boolean) {
|
setDraggingState(state: boolean) {
|
||||||
cursor.setDragging(state);
|
cursor.setDragging(state);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @see ISimulator
|
|
||||||
*/
|
|
||||||
setCopyState(state: boolean) {
|
setCopyState(state: boolean) {
|
||||||
cursor.setCopy(state);
|
cursor.setCopy(state);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* @see ISimulator
|
|
||||||
*/
|
|
||||||
clearState() {
|
clearState() {
|
||||||
cursor.release();
|
cursor.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
.lc-document {
|
.lc-document {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
&&-hidden {
|
&-hidden {
|
||||||
// todo:
|
// todo:
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,10 @@ import { RootSchema, NodeData, isDOMText, isJSExpression, NodeSchema } from '../
|
|||||||
import Node, { isNodeParent, insertChildren, insertChild, NodeParent } from './node/node';
|
import Node, { isNodeParent, insertChildren, insertChild, NodeParent } from './node/node';
|
||||||
import { Selection } from './selection';
|
import { Selection } from './selection';
|
||||||
import RootNode from './node/root-node';
|
import RootNode from './node/root-node';
|
||||||
import { ISimulator, ComponentInstance, Component, NodeInstance } from '../simulator';
|
import { ISimulator, Component } from '../simulator';
|
||||||
import { computed, obx } from '@recore/obx';
|
import { computed, obx } from '@recore/obx';
|
||||||
import Location from '../helper/location';
|
import Location from '../helper/location';
|
||||||
import { ComponentConfig } from '../component-config';
|
import { ComponentConfig } from '../component-config';
|
||||||
import { isElement } from '../../utils/is-element';
|
|
||||||
|
|
||||||
export default class DocumentModel {
|
export default class DocumentModel {
|
||||||
/**
|
/**
|
||||||
@ -234,8 +233,8 @@ export default class DocumentModel {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private _opened: boolean = true;
|
@obx.ref private _opened: boolean = true;
|
||||||
private _suspensed: boolean = false;
|
@obx.ref private _suspensed: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否不是激活的
|
* 是否不是激活的
|
||||||
@ -288,6 +287,8 @@ export default class DocumentModel {
|
|||||||
this._opened = true;
|
this._opened = true;
|
||||||
if (this._suspensed) {
|
if (this._suspensed) {
|
||||||
this.setSuspense(false);
|
this.setSuspense(false);
|
||||||
|
} else {
|
||||||
|
this.project.checkExclusive(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -220,7 +220,10 @@ export default class Dragon {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const checkcopy = (e: MouseEvent) => {
|
const checkcopy = (e: MouseEvent) => {
|
||||||
if (newBie || e.altKey || e.ctrlKey) {
|
if (newBie) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.altKey || e.ctrlKey) {
|
||||||
this.setCopyState(true);
|
this.setCopyState(true);
|
||||||
} else {
|
} else {
|
||||||
this.setCopyState(false);
|
this.setCopyState(false);
|
||||||
@ -243,7 +246,9 @@ export default class Dragon {
|
|||||||
|
|
||||||
const dragstart = () => {
|
const dragstart = () => {
|
||||||
const locateEvent = createLocateEvent(boostEvent);
|
const locateEvent = createLocateEvent(boostEvent);
|
||||||
if (!newBie) {
|
if (newBie) {
|
||||||
|
this.setCopyState(true);
|
||||||
|
} else {
|
||||||
chooseSensor(locateEvent);
|
chooseSensor(locateEvent);
|
||||||
}
|
}
|
||||||
this.setDraggingState(true);
|
this.setDraggingState(true);
|
||||||
@ -277,19 +282,19 @@ export default class Dragon {
|
|||||||
lastSensor.deactiveSensor();
|
lastSensor.deactiveSensor();
|
||||||
}
|
}
|
||||||
this.setNativeSelection(true);
|
this.setNativeSelection(true);
|
||||||
|
const copy = !newBie && this.isCopyState();
|
||||||
|
this.clearState();
|
||||||
|
|
||||||
let exception;
|
let exception;
|
||||||
if (this._dragging) {
|
if (this._dragging) {
|
||||||
this._dragging = false;
|
this._dragging = false;
|
||||||
try {
|
try {
|
||||||
this.emitter.emit('dragend', { dragObject, copy: this.isCopyState() });
|
this.emitter.emit('dragend', { dragObject, copy });
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
exception = ex;
|
exception = ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clearState();
|
|
||||||
|
|
||||||
alwaysListen.removeEventListener('mousemove', move, true);
|
alwaysListen.removeEventListener('mousemove', move, true);
|
||||||
alwaysListen.removeEventListener('mouseup', over, true);
|
alwaysListen.removeEventListener('mouseup', over, true);
|
||||||
alwaysListen.removeEventListener('mousedown', over, true);
|
alwaysListen.removeEventListener('mousedown', over, true);
|
||||||
|
|||||||
@ -1,21 +1,44 @@
|
|||||||
import { obx, computed } from '@recore/obx';
|
import { obx, computed } from '@recore/obx';
|
||||||
import { INodeSelector, IViewport } from '../simulator';
|
import { INodeSelector, IViewport } from '../simulator';
|
||||||
import Viewport from '../../builtins/simulator/host/viewport';
|
import { uniqueId } from '../../utils/unique-id';
|
||||||
|
|
||||||
export default class OffsetObserver {
|
export default class OffsetObserver {
|
||||||
@obx.ref hasOffset = false;
|
readonly id = uniqueId('oobx');
|
||||||
|
|
||||||
|
private lastOffsetLeft?: number;
|
||||||
|
private lastOffsetTop?: number;
|
||||||
|
private lastOffsetHeight?: number;
|
||||||
|
private lastOffsetWidth?: number;
|
||||||
|
@obx private height = 0;
|
||||||
|
@obx private width = 0;
|
||||||
|
@obx private left = 0;
|
||||||
|
@obx private top = 0;
|
||||||
|
|
||||||
|
@obx hasOffset = false;
|
||||||
@computed get offsetLeft() {
|
@computed get offsetLeft() {
|
||||||
return this.left + this.viewport.scrollX;
|
if (!this.viewport.scrolling || this.lastOffsetLeft == null) {
|
||||||
|
this.lastOffsetLeft = (this.left + this.viewport.scrollX) * this.scale;
|
||||||
|
}
|
||||||
|
return this.lastOffsetLeft;
|
||||||
}
|
}
|
||||||
@computed get offsetTop() {
|
@computed get offsetTop() {
|
||||||
return this.top + this.viewport.scrollY;
|
if (!this.viewport.scrolling || this.lastOffsetTop == null) {
|
||||||
|
this.lastOffsetTop = (this.top + this.viewport.scrollY) * this.scale;
|
||||||
|
}
|
||||||
|
return this.lastOffsetTop;
|
||||||
|
}
|
||||||
|
@computed get offsetHeight() {
|
||||||
|
if (!this.viewport.scrolling || this.lastOffsetHeight == null) {
|
||||||
|
this.lastOffsetHeight = this.height * this.scale;
|
||||||
|
}
|
||||||
|
return this.lastOffsetHeight;
|
||||||
|
}
|
||||||
|
@computed get offsetWidth() {
|
||||||
|
if (!this.viewport.scrolling || this.lastOffsetWidth == null) {
|
||||||
|
this.lastOffsetWidth = this.width * this.scale;
|
||||||
|
}
|
||||||
|
return this.lastOffsetWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@obx.ref height = 0;
|
|
||||||
@obx.ref width = 0;
|
|
||||||
@obx.ref left = 0;
|
|
||||||
@obx.ref top = 0;
|
|
||||||
|
|
||||||
@computed get scale() {
|
@computed get scale() {
|
||||||
return this.viewport.scale;
|
return this.viewport.scale;
|
||||||
@ -44,11 +67,13 @@ export default class OffsetObserver {
|
|||||||
if (!rect) {
|
if (!rect) {
|
||||||
this.hasOffset = false;
|
this.hasOffset = false;
|
||||||
} else {
|
} else {
|
||||||
this.hasOffset = true;
|
if (!this.viewport.scrolling || !this.hasOffset) {
|
||||||
this.height = rect.height;
|
this.height = rect.height;
|
||||||
this.width = rect.width;
|
this.width = rect.width;
|
||||||
this.left = rect.left;
|
this.left = rect.left;
|
||||||
this.top = rect.top;
|
this.top = rect.top;
|
||||||
|
this.hasOffset = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.pid = pid = (window as any).requestIdleCallback(compute);
|
this.pid = pid = (window as any).requestIdleCallback(compute);
|
||||||
};
|
};
|
||||||
@ -59,7 +84,7 @@ export default class OffsetObserver {
|
|||||||
this.pid = pid = (window as any).requestIdleCallback(compute);
|
this.pid = pid = (window as any).requestIdleCallback(compute);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
purge() {
|
||||||
if (this.pid) {
|
if (this.pid) {
|
||||||
(window as any).cancelIdleCallback(this.pid);
|
(window as any).cancelIdleCallback(this.pid);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export default class ProjectView extends Component<{ designer: Designer }> {
|
|||||||
render() {
|
render() {
|
||||||
const { designer } = this.props;
|
const { designer } = this.props;
|
||||||
// TODO: support splitview
|
// TODO: support splitview
|
||||||
|
console.info(designer.project.documents);
|
||||||
return (
|
return (
|
||||||
<div className="lc-project">
|
<div className="lc-project">
|
||||||
{designer.project.documents.map(doc => {
|
{designer.project.documents.map(doc => {
|
||||||
|
|||||||
@ -34,7 +34,14 @@ export interface IViewport extends IScrollable {
|
|||||||
* 内容矩形维度
|
* 内容矩形维度
|
||||||
*/
|
*/
|
||||||
readonly contentBounds: DOMRect;
|
readonly contentBounds: DOMRect;
|
||||||
|
/**
|
||||||
|
* 视口滚动对象
|
||||||
|
*/
|
||||||
readonly scrollTarget?: ScrollTarget;
|
readonly scrollTarget?: ScrollTarget;
|
||||||
|
/**
|
||||||
|
* 是否滚动中
|
||||||
|
*/
|
||||||
|
readonly scrolling: boolean;
|
||||||
/**
|
/**
|
||||||
* 内容当前滚动 X
|
* 内容当前滚动 X
|
||||||
*/
|
*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user