Peng Xiao 3 年之前
父節點
當前提交
281629a4bd

+ 2 - 29
tldraw/apps/tldraw-logseq/src/components/PrimaryTools/PrimaryTools.tsx

@@ -2,17 +2,14 @@ import * as React from 'react'
 import { useApp } from '@tldraw/react'
 import {
   CursorArrowIcon,
-  CircleIcon,
   Pencil1Icon,
-  VercelLogoIcon,
   ShadowIcon,
-  BoxIcon,
   VideoIcon,
   TextIcon,
 } from '@radix-ui/react-icons'
 import { observer } from 'mobx-react-lite'
 import { Button } from '~components/Button'
-import { EraserIcon, LineIcon, LogseqIcon } from '~components/icons'
+import { EraserIcon, ArrowIcon, LogseqIcon } from '~components/icons'
 
 export const PrimaryTools = observer(function PrimaryTools() {
   const app = useApp()
@@ -63,37 +60,13 @@ export const PrimaryTools = observer(function PrimaryTools() {
         >
           <EraserIcon />
         </Button>
-        <Button
-          data-tool="box"
-          data-selected={selectedToolId === 'box'}
-          onClick={handleToolClick}
-          onDoubleClick={handleToolDoubleClick}
-        >
-          <BoxIcon />
-        </Button>
-        <Button
-          data-tool="ellipse"
-          data-selected={selectedToolId === 'ellipse'}
-          onClick={handleToolClick}
-          onDoubleClick={handleToolDoubleClick}
-        >
-          <CircleIcon />
-        </Button>
-        <Button
-          data-tool="polygon"
-          data-selected={selectedToolId === 'polygon'}
-          onClick={handleToolClick}
-          onDoubleClick={handleToolDoubleClick}
-        >
-          <VercelLogoIcon />
-        </Button>
         <Button
           data-tool="line"
           data-selected={selectedToolId === 'line'}
           onClick={handleToolClick}
           onDoubleClick={handleToolDoubleClick}
         >
-          <LineIcon />
+          <ArrowIcon />
         </Button>
         <Button
           data-tool="text"

+ 7 - 2
tldraw/apps/tldraw-logseq/src/components/icons/LineIcon.tsx

@@ -1,6 +1,6 @@
 import * as React from 'react'
 
-export function LineIcon() {
+export function ArrowIcon() {
   return (
     <svg
       width="15"
@@ -9,7 +9,12 @@ export function LineIcon() {
       fill="currentColor"
       xmlns="http://www.w3.org/2000/svg"
     >
-      <path d="M3.64645 11.3536C3.45118 11.1583 3.45118 10.8417 3.64645 10.6465L11.1464 3.14645C11.3417 2.95118 11.6583 2.95118 11.8536 3.14645C12.0488 3.34171 12.0488 3.65829 11.8536 3.85355L4.35355 11.3536C4.15829 11.5488 3.84171 11.5488 3.64645 11.3536Z" />
+      <path
+        d="M3.64645 11.3536C3.45118 11.1583 3.45118 10.8417 3.64645 10.6465L10.2929 4L6 4C5.72386 4 5.5 3.77614 5.5 3.5C5.5 3.22386 5.72386 3 6 3L11.5 3C11.6326 3 11.7598 3.05268 11.8536 3.14645C11.9473 3.24022 12 3.36739 12 3.5L12 9.00001C12 9.27615 11.7761 9.50001 11.5 9.50001C11.2239 9.50001 11 9.27615 11 9.00001V4.70711L4.35355 11.3536C4.15829 11.5488 3.84171 11.5488 3.64645 11.3536Z"
+        fill="currentColor"
+        fill-rule="evenodd"
+        clip-rule="evenodd"
+      ></path>
     </svg>
   )
 }

+ 15 - 4
tldraw/apps/tldraw-logseq/src/lib/shapes/LineShape.tsx

@@ -4,7 +4,7 @@ import { SVGContainer, TLComponentProps } from '@tldraw/react'
 import { observer } from 'mobx-react-lite'
 import * as React from 'react'
 import { getArrowPath } from './arrow/arrowHelpers'
-import { StraightArrow } from './arrow/StraightArrow'
+import { Arrow } from './arrow/Arrow'
 import { CustomStyleProps, withClampedStyles } from './style-props'
 
 interface LineShapeProps extends CustomStyleProps, TLLineShapeProps {
@@ -25,7 +25,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
     },
     stroke: '#000000',
     fill: '#ffffff',
-    strokeWidth: 2,
+    strokeWidth: 1,
     opacity: 1,
     decorations: {
       end: Decoration.Arrow,
@@ -46,7 +46,7 @@ export class LineShape extends TLLineShape<LineShapeProps> {
     return (
       <SVGContainer {...events} opacity={isErasing ? 0.2 : opacity}>
         <g pointerEvents="none">
-          <StraightArrow
+          <Arrow
             style={{
               stroke,
               fill,
@@ -65,9 +65,20 @@ export class LineShape extends TLLineShape<LineShapeProps> {
   ReactIndicator = observer(() => {
     const {
       decorations,
+      strokeWidth,
       handles: { start, end },
     } = this.props
-    return <path d={getArrowPath(start.point, end.point, decorations?.start, decorations?.end)} />
+    return (
+      <path
+        d={getArrowPath(
+          { strokeWidth },
+          start.point,
+          end.point,
+          decorations?.start,
+          decorations?.end
+        )}
+      />
+    )
   })
 
   validateProps = (props: Partial<LineShapeProps>) => {

+ 7 - 8
tldraw/apps/tldraw-logseq/src/lib/shapes/LogseqPortalShape.tsx

@@ -1,16 +1,15 @@
 // TODO: provide "frontend.components.page/page" component?
 
 /* eslint-disable @typescript-eslint/no-explicit-any */
-import * as React from 'react'
 import { TLBoxShape, TLBoxShapeProps } from '@tldraw/core'
-import { HTMLContainer, SVGContainer, TLComponentProps, useApp } from '@tldraw/react'
+import { HTMLContainer, TLComponentProps, useApp } from '@tldraw/react'
 import { observer } from 'mobx-react-lite'
-import { CustomStyleProps, withClampedStyles } from './style-props'
+import * as React from 'react'
 import { TextInput } from '~components/inputs/TextInput'
-import { LogseqContext } from '~lib/logseq-context'
-import type { Shape } from '~lib'
 import { useCameraMovingRef } from '~hooks/useCameraMoving'
-import { BindingIndicator } from './BindingIndicator'
+import type { Shape } from '~lib'
+import { LogseqContext } from '~lib/logseq-context'
+import { CustomStyleProps, withClampedStyles } from './style-props'
 
 export interface LogseqPortalShapeProps extends TLBoxShapeProps, CustomStyleProps {
   type: 'logseq-portal'
@@ -98,7 +97,7 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
 
   ReactComponent = observer(({ events, isEditing, isErasing, isBinding }: TLComponentProps) => {
     const {
-      props: { opacity, pageId, size, strokeWidth },
+      props: { opacity, pageId, strokeWidth },
     } = this
 
     const app = useApp<Shape>()
@@ -139,7 +138,7 @@ export class LogseqPortalShape extends TLBoxShape<LogseqPortalShapeProps> {
           overflow: 'hidden',
           pointerEvents: 'all',
           opacity: isErasing ? 0.2 : opacity,
-          border: '1px solid rgb(52, 52, 52)',
+          border: `${strokeWidth}px solid rgb(52, 52, 52)`,
           backgroundColor: '#ffffff',
           boxShadow: isBinding ? '0px 0px 0 16px var(--tl-binding)' : '',
         }}

+ 1 - 1
tldraw/apps/tldraw-logseq/src/lib/shapes/arrow/StraightArrow.tsx → tldraw/apps/tldraw-logseq/src/lib/shapes/arrow/Arrow.tsx

@@ -18,7 +18,7 @@ interface ArrowSvgProps {
   decorationEnd: Decoration | undefined
 }
 
-export const StraightArrow = React.memo(function StraightArrow({
+export const Arrow = React.memo(function StraightArrow({
   style,
   start,
   end,

+ 6 - 142
tldraw/apps/tldraw-logseq/src/lib/shapes/arrow/arrowHelpers.ts

@@ -1,8 +1,6 @@
-import { Decoration, GeomUtils, rng, SvgPathUtils, TLLineShapeProps } from '@tldraw/core'
-import { intersectCircleCircle, intersectCircleLineSegment } from '@tldraw/intersect'
+import type { Decoration } from '@tldraw/core'
+import { intersectCircleLineSegment } from '@tldraw/intersect'
 import Vec from '@tldraw/vec'
-import getStroke from 'perfect-freehand'
-import { EASINGS } from './constants'
 
 export function getArrowArcPath(start: number[], end: number[], circle: number[], bend: number) {
   return [
@@ -20,103 +18,6 @@ export function getArrowArcPath(start: number[], end: number[], circle: number[]
   ].join(' ')
 }
 
-export function getBendPoint(handles: TLLineShapeProps['handles'], bend: number) {
-  const { start, end } = handles
-
-  const dist = Vec.dist(start.point, end.point)
-
-  const midPoint = Vec.med(start.point, end.point)
-
-  const bendDist = (dist / 2) * bend
-
-  const u = Vec.uni(Vec.vec(start.point, end.point))
-
-  const point = Vec.toFixed(
-    Math.abs(bendDist) < 10 ? midPoint : Vec.add(midPoint, Vec.mul(Vec.per(u), bendDist))
-  )
-
-  return point
-}
-
-export function renderFreehandArrowShaft(
-  id: string,
-  start: number[],
-  end: number[],
-  decorationStart: Decoration | undefined,
-  decorationEnd: Decoration | undefined
-) {
-  const getRandom = rng(id)
-  const strokeWidth = 2
-  const startPoint = decorationStart ? Vec.nudge(start, end, strokeWidth) : start
-  const endPoint = decorationEnd ? Vec.nudge(end, start, strokeWidth) : end
-  const stroke = getStroke([startPoint, endPoint], {
-    size: strokeWidth,
-    thinning: 0.618 + getRandom() * 0.2,
-    easing: EASINGS.easeOutQuad,
-    simulatePressure: true,
-    streamline: 0,
-    last: true,
-  })
-  return SvgPathUtils.getSvgPathFromStroke(stroke)
-}
-
-export function renderCurvedFreehandArrowShaft(
-  id: string,
-  start: number[],
-  end: number[],
-  decorationStart: Decoration | undefined,
-  decorationEnd: Decoration | undefined,
-  center: number[],
-  radius: number,
-  length: number,
-  easing: (t: number) => number
-) {
-  const getRandom = rng(id)
-  const strokeWidth = 2
-  const startPoint = decorationStart ? Vec.rotWith(start, center, strokeWidth / length) : start
-  const endPoint = decorationEnd ? Vec.rotWith(end, center, -(strokeWidth / length)) : end
-  const startAngle = Vec.angle(center, startPoint)
-  const endAngle = Vec.angle(center, endPoint)
-  const points: number[][] = []
-  const count = 8 + Math.floor((Math.abs(length) / 20) * 1 + getRandom() / 2)
-  for (let i = 0; i < count; i++) {
-    const t = easing(i / count)
-    const angle = GeomUtils.lerpAngles(startAngle, endAngle, t)
-    points.push(Vec.toFixed(Vec.nudgeAtAngle(center, angle, radius)))
-  }
-  const stroke = getStroke([startPoint, ...points, endPoint], {
-    size: 1 + strokeWidth,
-    thinning: 0.618 + getRandom() * 0.2,
-    easing: EASINGS.easeOutQuad,
-    simulatePressure: false,
-    streamline: 0,
-    last: true,
-  })
-  return SvgPathUtils.getSvgPathFromStroke(stroke)
-}
-
-export function getCtp(start: number[], bend: number[], end: number[]) {
-  return GeomUtils.circleFromThreePoints(start, end, bend)
-}
-
-export function getCurvedArrowHeadPoints(
-  A: number[],
-  r1: number,
-  C: number[],
-  r2: number,
-  sweep: boolean
-) {
-  const ints = intersectCircleCircle(A, r1 * 0.618, C, r2).points
-  if (!ints) {
-    console.warn('Could not find an intersection for the arrow head.')
-    return { left: A, right: A }
-  }
-  const int = sweep ? ints[0] : ints[1]
-  const left = int ? Vec.nudge(Vec.rotWith(int, A, Math.PI / 6), A, r1 * -0.382) : A
-  const right = int ? Vec.nudge(Vec.rotWith(int, A, -Math.PI / 6), A, r1 * -0.382) : A
-  return { left, right }
-}
-
 export function getStraightArrowHeadPoints(A: number[], B: number[], r: number) {
   const ints = intersectCircleLineSegment(A, r, A, B).points
   if (!ints) {
@@ -129,29 +30,21 @@ export function getStraightArrowHeadPoints(A: number[], B: number[], r: number)
   return { left, right }
 }
 
-export function getCurvedArrowHeadPath(
-  A: number[],
-  r1: number,
-  C: number[],
-  r2: number,
-  sweep: boolean
-) {
-  const { left, right } = getCurvedArrowHeadPoints(A, r1, C, r2, sweep)
-  return `M ${left} L ${A} ${right}`
-}
-
 export function getStraightArrowHeadPath(A: number[], B: number[], r: number) {
   const { left, right } = getStraightArrowHeadPoints(A, B, r)
   return `M ${left} L ${A} ${right}`
 }
 
 export function getArrowPath(
+  style: {
+    strokeWidth: number
+  },
   start: number[],
   end: number[],
   decorationStart: Decoration | undefined,
   decorationEnd: Decoration | undefined
 ) {
-  const strokeWidth = 2
+  const strokeWidth = style.strokeWidth
   const arrowDist = Vec.dist(start, end)
   const arrowHeadLength = Math.min(arrowDist / 3, strokeWidth * 8)
   const path: (string | number)[] = []
@@ -164,32 +57,3 @@ export function getArrowPath(
   }
   return path.join(' ')
 }
-
-export function getArcPoints(start: number[], bend: number[], end: number[]) {
-  if (Vec.dist2(bend, Vec.med(start, end)) <= 4) return [start, end]
-  // The arc is curved; calculate twenty points along the arc
-  const points: number[][] = []
-  const circle = getCtp(start, bend, end)
-  const center = [circle[0], circle[1]]
-  const radius = circle[2]
-  const startAngle = Vec.angle(center, start)
-  const endAngle = Vec.angle(center, end)
-  for (let i = 1 / 20; i < 1; i += 1 / 20) {
-    const angle = GeomUtils.lerpAngles(startAngle, endAngle, i)
-    points.push(Vec.nudgeAtAngle(center, angle, radius))
-  }
-  return points
-}
-
-export function isAngleBetween(a: number, b: number, c: number): boolean {
-  if (c === a || c === b) return true
-  const PI2 = Math.PI * 2
-  const AB = (b - a + PI2) % PI2
-  const AC = (c - a + PI2) % PI2
-  return AB <= Math.PI !== AC > AB
-}
-
-export function getArcLength(C: number[], r: number, A: number[], B: number[]): number {
-  const sweep = GeomUtils.getSweep(C, A, B)
-  return r * (2 * Math.PI) * (sweep / (2 * Math.PI))
-}