Add onElementClick and export sceneCoordsToViewportCoords
This commit is contained in:
parent
47498796e0
commit
5f4a5b1789
@ -3091,15 +3091,13 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
event: React.PointerEvent<HTMLCanvasElement>,
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
) => {
|
) => {
|
||||||
this.lastPointerUp = event;
|
this.lastPointerUp = event;
|
||||||
if (this.deviceType.isTouchScreen) {
|
let hitElement;
|
||||||
|
if (this.deviceType.isTouchScreen || this.props.onElementClick) {
|
||||||
const scenePointer = viewportCoordsToSceneCoords(
|
const scenePointer = viewportCoordsToSceneCoords(
|
||||||
{ clientX: event.clientX, clientY: event.clientY },
|
{ clientX: event.clientX, clientY: event.clientY },
|
||||||
this.state,
|
this.state,
|
||||||
);
|
);
|
||||||
const hitElement = this.getElementAtPosition(
|
hitElement = this.getElementAtPosition(scenePointer.x, scenePointer.y);
|
||||||
scenePointer.x,
|
|
||||||
scenePointer.y,
|
|
||||||
);
|
|
||||||
this.hitLinkElement = this.getElementLinkAtPosition(
|
this.hitLinkElement = this.getElementLinkAtPosition(
|
||||||
scenePointer,
|
scenePointer,
|
||||||
hitElement,
|
hitElement,
|
||||||
@ -3112,6 +3110,23 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
this.redirectToLink(event, this.deviceType.isTouchScreen);
|
this.redirectToLink(event, this.deviceType.isTouchScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.state.elementType === "selection" &&
|
||||||
|
this.props.onElementClick &&
|
||||||
|
hitElement
|
||||||
|
) {
|
||||||
|
const threshold = 5;
|
||||||
|
const isSinglePointClick =
|
||||||
|
distance2d(
|
||||||
|
this.lastPointerDown!.clientX,
|
||||||
|
this.lastPointerDown!.clientY,
|
||||||
|
this.lastPointerUp!.clientX,
|
||||||
|
this.lastPointerUp!.clientY,
|
||||||
|
) <= threshold;
|
||||||
|
if (isSinglePointClick) {
|
||||||
|
this.props.onElementClick(hitElement, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.removePointer(event);
|
this.removePointer(event);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4517,6 +4532,7 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
// Code below handles selection when element(s) weren't
|
// Code below handles selection when element(s) weren't
|
||||||
// drag or added to selection on pointer down phase.
|
// drag or added to selection on pointer down phase.
|
||||||
const hitElement = pointerDownState.hit.element;
|
const hitElement = pointerDownState.hit.element;
|
||||||
|
|
||||||
if (isEraserActive(this.state)) {
|
if (isEraserActive(this.state)) {
|
||||||
const draggedDistance = distance2d(
|
const draggedDistance = distance2d(
|
||||||
this.lastPointerDown!.clientX,
|
this.lastPointerDown!.clientX,
|
||||||
@ -4550,7 +4566,6 @@ class App extends React.Component<AppProps, AppState> {
|
|||||||
} else if (Object.keys(pointerDownState.elementIdsToErase).length) {
|
} else if (Object.keys(pointerDownState.elementIdsToErase).length) {
|
||||||
this.restoreReadyToEraseElements(pointerDownState);
|
this.restoreReadyToEraseElements(pointerDownState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
hitElement &&
|
hitElement &&
|
||||||
!pointerDownState.drag.hasOccurred &&
|
!pointerDownState.drag.hasOccurred &&
|
||||||
|
@ -9,7 +9,12 @@ import { MIME_TYPES } from "../../../constants";
|
|||||||
|
|
||||||
// This is so that we use the bundled excalidraw.development.js file instead
|
// This is so that we use the bundled excalidraw.development.js file instead
|
||||||
// of the actual source code
|
// of the actual source code
|
||||||
const { exportToCanvas, exportToSvg, exportToBlob } = window.Excalidraw;
|
const {
|
||||||
|
exportToCanvas,
|
||||||
|
exportToSvg,
|
||||||
|
exportToBlob,
|
||||||
|
sceneCoordsToViewportCoords,
|
||||||
|
} = window.Excalidraw;
|
||||||
const Excalidraw = window.Excalidraw.default;
|
const Excalidraw = window.Excalidraw.default;
|
||||||
|
|
||||||
const STAR_SVG = (
|
const STAR_SVG = (
|
||||||
@ -56,7 +61,7 @@ const renderFooter = () => {
|
|||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const excalidrawRef = useRef(null);
|
const excalidrawRef = useRef(null);
|
||||||
|
const excalidrawWrapperRef = useRef(null);
|
||||||
const [viewModeEnabled, setViewModeEnabled] = useState(false);
|
const [viewModeEnabled, setViewModeEnabled] = useState(false);
|
||||||
const [zenModeEnabled, setZenModeEnabled] = useState(false);
|
const [zenModeEnabled, setZenModeEnabled] = useState(false);
|
||||||
const [gridModeEnabled, setGridModeEnabled] = useState(false);
|
const [gridModeEnabled, setGridModeEnabled] = useState(false);
|
||||||
@ -200,6 +205,39 @@ export default function App() {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onElementClick = (element) => {
|
||||||
|
if (element.type === "custom" && element.customType === "comment") {
|
||||||
|
const { x: viewPortX, y: viewPortY } = sceneCoordsToViewportCoords(
|
||||||
|
{
|
||||||
|
sceneX: element.x,
|
||||||
|
sceneY: element.y,
|
||||||
|
},
|
||||||
|
excalidrawRef.current.getAppState(),
|
||||||
|
);
|
||||||
|
const textarea = document.createElement("textarea");
|
||||||
|
Object.assign(textarea.style, {
|
||||||
|
position: "absolute",
|
||||||
|
display: "inline-block",
|
||||||
|
left: `${viewPortX + element.width / 2}px`,
|
||||||
|
top: `${viewPortY + element.height / 2}px`,
|
||||||
|
height: `${100}px`,
|
||||||
|
width: `${100}px`,
|
||||||
|
zIndex: 10,
|
||||||
|
className: "comment-textarea",
|
||||||
|
whiteSpace: "pre-wrap",
|
||||||
|
fontSize: "13px",
|
||||||
|
});
|
||||||
|
textarea.placeholder = "Start typing your comments";
|
||||||
|
textarea.onblur = () => {
|
||||||
|
textarea.remove();
|
||||||
|
};
|
||||||
|
excalidrawWrapperRef.current
|
||||||
|
.querySelector(".excalidraw")
|
||||||
|
.append(textarea);
|
||||||
|
textarea.focus();
|
||||||
|
}
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
<h1> Excalidraw Example</h1>
|
<h1> Excalidraw Example</h1>
|
||||||
@ -273,7 +311,7 @@ export default function App() {
|
|||||||
Switch to Dark Theme
|
Switch to Dark Theme
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="excalidraw-wrapper">
|
<div className="excalidraw-wrapper" ref={excalidrawWrapperRef}>
|
||||||
<Excalidraw
|
<Excalidraw
|
||||||
ref={excalidrawRef}
|
ref={excalidrawRef}
|
||||||
initialData={initialStatePromiseRef.current.promise}
|
initialData={initialStatePromiseRef.current.promise}
|
||||||
@ -295,6 +333,7 @@ export default function App() {
|
|||||||
onLinkOpen={onLinkOpen}
|
onLinkOpen={onLinkOpen}
|
||||||
renderCustomElementWidget={renderCustomElementWidget}
|
renderCustomElementWidget={renderCustomElementWidget}
|
||||||
customElementsConfig={getCustomElementsConfig()}
|
customElementsConfig={getCustomElementsConfig()}
|
||||||
|
onElementClick={onElementClick}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ const Excalidraw = (props: ExcalidrawProps) => {
|
|||||||
generateIdForFile,
|
generateIdForFile,
|
||||||
onLinkOpen,
|
onLinkOpen,
|
||||||
renderCustomElementWidget,
|
renderCustomElementWidget,
|
||||||
|
onElementClick,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const canvasActions = props.UIOptions?.canvasActions;
|
const canvasActions = props.UIOptions?.canvasActions;
|
||||||
@ -109,6 +110,7 @@ const Excalidraw = (props: ExcalidrawProps) => {
|
|||||||
onLinkOpen={onLinkOpen}
|
onLinkOpen={onLinkOpen}
|
||||||
renderCustomElementWidget={renderCustomElementWidget}
|
renderCustomElementWidget={renderCustomElementWidget}
|
||||||
customElementsConfig={customElementsConfig}
|
customElementsConfig={customElementsConfig}
|
||||||
|
onElementClick={onElementClick}
|
||||||
/>
|
/>
|
||||||
</InitializeApp>
|
</InitializeApp>
|
||||||
);
|
);
|
||||||
@ -207,3 +209,5 @@ export {
|
|||||||
newElementWith,
|
newElementWith,
|
||||||
bumpVersion,
|
bumpVersion,
|
||||||
} from "../../element/mutateElement";
|
} from "../../element/mutateElement";
|
||||||
|
|
||||||
|
export { sceneCoordsToViewportCoords } from "../../utils";
|
||||||
|
@ -263,6 +263,10 @@ export interface ExcalidrawProps {
|
|||||||
) => void;
|
) => void;
|
||||||
renderCustomElementWidget?: (appState: AppState) => void;
|
renderCustomElementWidget?: (appState: AppState) => void;
|
||||||
customElementsConfig?: CustomElementConfig[];
|
customElementsConfig?: CustomElementConfig[];
|
||||||
|
onElementClick: (
|
||||||
|
element: NonDeleted<ExcalidrawElement>,
|
||||||
|
event: React.PointerEvent<HTMLCanvasElement>,
|
||||||
|
) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SceneData = {
|
export type SceneData = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user