Skip to content

Commit

Permalink
Merge pull request #15 from nextjs-particlex-theme/feature/draggableSvg
Browse files Browse the repository at this point in the history
feat: 流程图提供拖拽选项
  • Loading branch information
IceOfSummer authored Sep 26, 2024
2 parents 24d18fa + 98353d5 commit d33a493
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use client'

import React, { useEffect, useRef, useState } from 'react'

interface DraggableSvgProps {
pruneSvgHTML: string
}

type DragState = {
startX: number
startY: number
eleOffset: EleOffset
dragging: boolean
}

type EleOffset = {
x: number
y: number
}

const DraggableSvg: React.FC<DraggableSvgProps> = props => {
const holderRef = useRef<HTMLDivElement>(null)
const [eleOffset, setEleOffset] = useState<EleOffset>({ x: 0, y: 0 })
const state = useRef<DragState>({ startX: 0, startY: 0, dragging: false, eleOffset: { x: 0, y: 0 } })

useEffect(() => {
const holder = holderRef.current
if (!holder) {
return
}
const mouseDownEvtHandler = (ev: MouseEvent) => {
const current = state.current
current.startX = ev.x
current.startY = ev.y
current.dragging = true
}

const mouseUpEvtHandler = (ev: MouseEvent) => {
const current = state.current
if (!current.dragging) {
return
}
current.dragging = false
current.eleOffset = {
x: current.eleOffset.x - (current.startX - ev.x),
y: current.eleOffset.y - (current.startY - ev.y)
}
}

const mouseMoveEvtHandler = (ev: MouseEvent) => {
const current = state.current
if (!current.dragging) {
return
}
setEleOffset({
x: current.eleOffset.x - (current.startX - ev.x),
y: current.eleOffset.y - (current.startY - ev.y)
})
}

holder.addEventListener('mousedown', mouseDownEvtHandler)
holder.addEventListener('mouseup', mouseUpEvtHandler)
holder.addEventListener('mousemove', mouseMoveEvtHandler)
holder.addEventListener('mouseout', mouseUpEvtHandler)

return () => {
holder.removeEventListener('mousedown', mouseDownEvtHandler)
holder.removeEventListener('mouseup', mouseUpEvtHandler)
holder.removeEventListener('mousemove', mouseMoveEvtHandler)
holder.removeEventListener('mouseout', mouseUpEvtHandler)
}
}, [])

return (
<div style={{ color: 'var(--color-card)', display: 'flex', justifyContent: 'center', overflow: 'hidden', backgroundColor: 'var(--color-card)' }}>
<div ref={holderRef} dangerouslySetInnerHTML={{ __html: props.pruneSvgHTML }} style={{ transform: `translate(${eleOffset.x}px, ${eleOffset.y}px)` }}></div>
</div>
)
}

export default DraggableSvg
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import type React from 'react'
import type { PintoraConfig } from '@pintora/cli'
import { render } from '@pintora/cli'
import DraggableSvg from '@/api/markdown-parser/impl/mdx/components/PintoraDiagram/DraggableSvg'


interface PintoraDiagramProps {
code: string
config?: PintoraConfig
draggable?: boolean
}

/**
* @see https://pintorajs.vercel.app/
*/
const PintoraDiagram: React.FC<PintoraDiagramProps> = async props => {
// const r = pintora.parseAndDraw(props.code, { config: props.config })
// console.log(r)
const svg = await render({
code: props.code,
pintoraConfig: props.config,
mimeType: 'image/svg+xml',
width: 800,
backgroundColor: 'currentColor',
renderInSubprocess: false
})
return (
<div style={{ color: 'var(--color-card)', display: 'flex', justifyContent: 'center' }} dangerouslySetInnerHTML={{ __html: svg }}></div>
)
}) as string

if (props.draggable) {
return (
<DraggableSvg pruneSvgHTML={svg}/>
)
}
return <div style={{ color: 'var(--color-card)', display: 'flex', justifyContent: 'center' }}
dangerouslySetInnerHTML={{ __html: svg }}></div>
}

export default PintoraDiagram

0 comments on commit d33a493

Please sign in to comment.