[FEATURE] 初始化YasatInkCanvas并初步实现backgroundColor,正在实现稿纸格式。

This commit is contained in:
Dubi906w 2024-02-11 15:17:20 +07:00
parent ef93865a2a
commit faf87ea0d4
14 changed files with 3105 additions and 2293 deletions

View File

@ -2,5 +2,12 @@
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="false" level="TEXT ATTRIBUTES" enabled_by_default="false" editorAttributes="TEXT_STYLE_SUGGESTION" />
<inspection_tool class="com.haulmont.rcb.ArrayToJSXMapInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.ConvertUnresolvedToStateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.EmptyAttributeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.EmptyRefInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.ExhaustiveDepsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.NonExistentPropUsageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="com.haulmont.rcb.PaletteExtLocalInspection" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@ -5,4 +5,3 @@
<h1 style="text-align:center;">dot-yasat</h1>
<div style="text-align:center; margin-top:1rem">基于Electron与PyQt开发的PPT批注工具</div>
<div style="text-align:center; margin-top:1rem">此项目不再积极维护</div>

View File

@ -2,6 +2,7 @@ import { resolve } from 'path'
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
import react from '@vitejs/plugin-react'
import UnoCSS from 'unocss/vite'
import million from 'million/compiler'
export default defineConfig({
main: {
@ -17,5 +18,8 @@ export default defineConfig({
}
},
plugins: [react(),UnoCSS()],
server: {
host: "0.0.0.0"
}
}
})

View File

@ -26,9 +26,13 @@
"@radix-ui/themes": "^2.0.1",
"@studio-freight/react-lenis": "^0.0.38",
"@unocss/reset": "^0.57.5",
"ahooks": "^3.7.10",
"electron-updater": "^6.1.7",
"express": "^4.18.2",
"fabric": "^5.3.0",
"million": "^3.0.3",
"pako": "^2.1.0",
"perfect-freehand": "^1.2.0",
"react": "^18.2.0",
"react-aria-components": "^1.0.1",
"react-dom": "^18.2.0",

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ function createWindow() {
hasShadow: false,
movable: false,
resizable: false,
focusable: false,
focusable: process.platform === 'darwin', // 因为macOS只会在可focus的情况下显示自定义cursor
backgroundColor: "#00000000",
...(process.platform === 'darwin' ? { acceptFirstMouse: true } : {}),
...(process.platform === 'darwin' ? { visualEffectState: "inactive" } : {}),

View File

@ -1,17 +1,40 @@
import YasatMainWindow from './YasatMainWindow.jsx'
import DotYasatLogo from "./assets/dot-yasat-logo.png"
import YasatInkCanvas from './YasatInkCanvas'
import { useEffect, useRef } from 'react'
function App() {
const inkCanvasRef = useRef(null);
useEffect(() => {
// setTimeout(()=>{
// inkCanvasRef.current["_"]({
// action: "SET_BACKGROUND",
// backgroundColor: "rgba(0,0,0,1)"
// })
// },2000);
inkCanvasRef.current["_"]({
action: "SET_BACKGROUND_COLOR",
value: "blackboard-green"
})
}, []);
return (
<>
{/*<div className="w-screen h-screen bg-#274C43 overflow-hidden flex items-end justify-center relative">*/}
<div className="w-screen h-screen bg-transparent overflow-hidden flex items-end justify-center relative">
<YasatMainWindow/>
<div className="absolute z-0 inset-0 flex flex-col justify-center items-center pointer-events-none">
<img src={DotYasatLogo} className="opacity-20 h-48 invert"/>
<div className="text-3xl font-bold opacity-20 text-zinc-200">流利书写流畅教学</div>
<div className="text-lg font-medium mt-4 opacity-15 text-zinc-200 flex items-center">
<YasatInkCanvas
wrapperClassName="absolute z-2 top-0 left-0 w-screen h-screen"
canvasClassName=""
width="full" height="full"
ref={inkCanvasRef}
/>
<div className="absolute z-1 pointer-events-none inset-0 flex flex-col justify-center items-center pointer-events-none">
<img src={DotYasatLogo} className="opacity-20 h-48"/>
<div className="text-3xl font-bold opacity-20 text-zinc-800">流利书写流畅教学</div>
<div className="text-lg font-medium mt-4 opacity-15 text-zinc-800 flex items-center">
<div>巴南中学高2027级15班刘晨曦用</div>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" viewBox="0 0 24 24" strokeWidth={2} stroke="currentColor" fill="none" strokeLinecap="round" strokeLinejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
@ -19,7 +42,7 @@ function App() {
</svg>
<div>开发</div>
</div>
<div className="text-lg mt-12 opacity-15 text-zinc-200 flex items-center space-x-2">
<div className="text-lg mt-12 opacity-15 text-zinc-800 flex items-center space-x-2">
<svg xmlns="http://www.w3.org/2000/svg" className="h-5.5 w-5.5" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" fill="none" strokeLinecap="round" strokeLinejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0" />
@ -30,7 +53,6 @@ function App() {
</div>
</div>
</div>
</>
)
}

View File

@ -0,0 +1,149 @@
import { forwardRef, useEffect, useImperativeHandle, useMemo, useReducer, useRef } from 'react'
import { fabric } from "fabric"
import { useSize } from 'ahooks'
import resources_tianzige from "./resources/manuscript/tianZiGe.png"
import resources_mizige from "./resources/manuscript/miZiGe.png"
import resources_english from "./resources/manuscript/english.png"
/**
* @param state
* @param {object} action
* */
function _reducer(state, action) {
switch (action.action) {
case "SET_BACKGROUND_COLOR": {
if ((["transparent","blackboard-green","black","gray","zinc","white","pure-white"]).includes(action.value)===true) {
return { ...state, backgroundColor:action.value };
} else {
console.error(`"SET_BACKGROUND_COLOR" 仅接受 "transparent" | "blackboard-green" | "black" | "gray" | "zinc" | "white" | "pure-white",其他的非法值不被允许!没有任何值被更改!`);
return { ...state };
}
}
}
}
export default forwardRef(
/**
* @param {{
* wrapperClassName :string,
* canvasClassName :string,
* width :string | number,
* height :string | number,
* backgroundColor: "transparent" | "blackboard-green" | "black" | "gray" | "zinc" | "white" | "pure-white",
* }} props
* @param ref
* */
function YasatInkCanvas(props, ref) {
const canvasRef = useRef(null);
const fabricRef = useRef(null);
const size = useSize(document.querySelector("html"));
const [state, dispatch] = useReducer(_reducer, {
/*
* 此处接受 "transparent" | "blackboard-green" | "black" | "gray" | "zinc" | "white" | "pure-white"
* 使用 "SET_BACKGROUND_COLOR" 来修改背景颜色或者通过给组件传入backgroundColor props来设置背景颜色
* 注意传入backgroundColor props后将会让此值成为"component-props-driven"模式无法使用 "SET_BACKGROUND_COLOR" 来修改背景颜色
* 如果需要设置自定义背景格式请使用 "SET_CUSTOM_BACKGROUND"
* */
backgroundColor: "transparent",
// 稿div
enableManuscriptFormat: true,
/*
* 设置背景稿纸格式
* 支持 "chinese-tian" | "chinese-mi" | "english" | "music-fiveline"
* */
manuscriptType: "english",
});
const actualBackgroundColor = useMemo(() => (
(props.backgroundColor??state.backgroundColor)==="transparent"?"rgba(0,0,0,0)":
(props.backgroundColor??state.backgroundColor)==="blackboard-green"?"rgba(22,55,36,1)":
(props.backgroundColor??state.backgroundColor).backgroundColor==="black"?"rgba(0,0,0,1)":
(props.backgroundColor??state.backgroundColor).backgroundColor==="gray"?"#111827":
(props.backgroundColor??state.backgroundColor).backgroundColor==="zinc"?"#18181b":
(props.backgroundColor??state.backgroundColor).backgroundColor==="white"?"#f4f4f5":
(props.backgroundColor??state.backgroundColor).backgroundColor==="pure-white"?"rgba(255,255,255,1)":
// fallback value
"rgba(0,0,0,0)"), [props.backgroundColor,state.backgroundColor]);
//
useEffect(() => {
fabricRef.current?.setDimensions({
width: props.width === "full" ? size.width : props.width,
height: props.height === "full" ? size.height : props.height,
})
}, [size.width, size.height, props.height, props.width]);
// fabric.js
useEffect(() => {
console.log("%cYasatInkCanvas v0.1.0","font-size:18pt;font-weight:bold;")
fabricRef.current = new fabric.Canvas(canvasRef.current);
//
fabricRef.current?.setDimensions({
width: props.width === "full" ? size.width : props.width,
height: props.height === "full" ? size.height : props.height,
})
//
fabricRef.current?.setBackgroundColor("rgba(0,0,0,0)")
// fabric.js
return () => {
fabricRef.current.dispose();
fabricRef.current = undefined;
}
}, [])
// backgroundColorEffect
useEffect(() => {
if (state.enableManuscriptFormat===true) {
fabricRef.current?.setBackgroundColor("rgba(0,0,0,0)",fabricRef.current?.renderAll.bind(fabricRef.current))
} else {
fabricRef.current?.setBackgroundColor(actualBackgroundColor, fabricRef.current?.renderAll.bind(fabricRef.current));
}
}, [state.backgroundColor,props.backgroundColor]);
// _ ref
useImperativeHandle(
ref,
() => {
return {
_: (action)=>{
dispatch({
fabric: fabricRef.current,
...action
})
}
}
},
[state],
);
return (
<>
<div className={"relative "+props.wrapperClassName}>
{state.enableManuscriptFormat?(
<div className="manuscript-layer absolute top-0 left-0 w-full h-full -z-1 flex items-center justify-center" style={{backgroundColor:actualBackgroundColor}}>
{state.manuscriptType==="chinese-tian"||state.manuscriptType==="chinese-mi"||state.manuscriptType==="english"?(
<div className={"grid grid-cols-5 w-fit h-fit "+(state.manuscriptType!=="english"?"border-l-2 border-r-2 border-t-1 border-b-1 border-white":"")}>
{(new Array(5).fill(null)).map((_,__)=>
<img alt="" key={__} src={state.manuscriptType==="chinese-mi"?resources_mizige:state.manuscriptType==="chinese-tian"?resources_tianzige:resources_english} className="h-15vw object-contain" />
)}
<div className={"col-span-5 -mt-1 "+(state.manuscriptType!=="english"?"ring-2 ring-inset ring-white h-4vw":"h-10vw")}></div>
{(new Array(5).fill(null)).map((_,__)=>
<img alt="" key={__} src={state.manuscriptType==="chinese-mi"?resources_mizige:state.manuscriptType==="chinese-tian"?resources_tianzige:resources_english} className="h-15vw object-contain" />
)}
</div>
):void 0}
</div>
):void 0}
<canvas ref={canvasRef} className={props.canvasClassName} />
</div>
</>
)
}
)

View File

@ -1301,6 +1301,7 @@ export default function YasatMainWindow(props) {
return (
<>
<div className="flex justify-center fixed z-5 bottom-0 left-0 w-screen">
<div className="flex flex-col h-fit w-fit space-y-1 relative">
{/*penMenu*/}
@ -3244,7 +3245,7 @@ export default function YasatMainWindow(props) {
</div>
{/*LeftToolBar*/}
<div className="fixed bottom-0 left-0 w-fit h-fit">
<div className="z-10 fixed bottom-0 left-0 w-fit h-fit">
<div className="flex flex-col h-fit w-fit space-y-1 relative">
{/*mainMenu*/}
<div className="relative flex h-0 w-full justify-start">
@ -3601,7 +3602,7 @@ export default function YasatMainWindow(props) {
</div>
{/*RightToolBar*/}
<div className="fixed bottom-0 right-0 w-fit h-fit">
<div className="z-10 fixed bottom-0 right-0 w-fit h-fit">
<div className="flex flex-col h-fit w-fit space-y-1 relative">
<div className="flex h-fit w-fit items-center justify-center space-x-1">
<div className="rounded-lg transition-all bg-zinc-50 border border-zinc-300 shadow-md flex w-fit items-center justify-center select-none overflow-clip">
@ -3687,6 +3688,7 @@ export default function YasatMainWindow(props) {
</div>
</div>
</div>
</div>
<Toaster position="bottom-center" containerClassName="mb-18" />
<YasatSettingsWindow ref={YasatSettingsWindowRef}/>

View File

@ -101,7 +101,7 @@ export default forwardRef(function YasatSettingsWindow(props, ref){
</div>
</div>
<ReactLenis options={{
duraton : 0.05,
duration : 0.2,
}} className="select-none pr-6 w-full grow overflow-y-scroll scrollbar scrollbar-thumb-color-zinc-800/50 scrollbar-w-1 scrollbar-rounded overflow-x-clip flex flex-col">
<div className="h-fit w-full">
<div className="text-center text-sm font-medium text-zinc-800 mb-2 select-none">设置将自动保存若无特别说明则选项修改后立刻生效</div>

View File

@ -6,7 +6,7 @@ import './main.css'
import 'virtual:uno.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
// <React.StrictMode>
<App />
</React.StrictMode>,
// </React.StrictMode>,
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB