Skip to content

Commit

Permalink
feat(text):
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepy-zone committed Nov 7, 2023
1 parent a4c1628 commit 0ac00c4
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 20 deletions.
6 changes: 0 additions & 6 deletions src/editor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { fabric } from 'fabric';
import { calcCanvasZoomLevel } from '@/utils/helper';
import { createTextbox } from './textbox';

export default class Editor {
public canvas: fabric.Canvas;
Expand All @@ -24,7 +23,6 @@ export default class Editor {
private _initFabric () {
const { canvasEl, workspaceEl } = this._options;
this.canvas = new fabric.Canvas(canvasEl, {
selection: false,
containerClass: 'fabritor-canvas',
enableRetinaScaling: true,
fireRightClick: true,
Expand Down Expand Up @@ -95,10 +93,6 @@ export default class Editor {
this.canvas.on('mouse:down', sketchEventHandler?.clickHandler);
}

public async addTextbox () {
return createTextbox({}, this);
}

public destroy () {
if (this.canvas) {
this.canvas.dispose();
Expand Down
17 changes: 14 additions & 3 deletions src/editor/textbox.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { fabric } from 'fabric';
import { TEXTBOX_DEFAULT_CONFIG } from '../utils/constants';
import { uuid, loadFont } from '@/utils';
import { getGlobalEditor } from '@/utils/global';

export const createTextbox = async (options, editor) => {
export const createTextbox = async (options) => {
const { text = '', left, top, fontFamily, ...rest } = options || {};
const editor = getGlobalEditor();
const { canvas, sketch } = editor;

const textBox = new fabric.Textbox(text || '双击进行编辑', {
Expand All @@ -15,20 +17,29 @@ export const createTextbox = async (options, editor) => {
if (left == null) {
// @ts-ignore
textBox.set('left', sketch.width / 2 - textBox.width / 2);
} else {
textBox.set('left', left);
}
if (top == null) {
// @ts-ignore
textBox.set('top', sketch.height / 2 - textBox.calcTextHeight() / 2);
} else {
textBox.set('top', top);
}

textBox.setControlVisible('mt', false);
textBox.setControlVisible('mb', false);

if (fontFamily) {
await loadFont(fontFamily);
textBox.set('fontFamily', fontFamily);
try {
await loadFont(fontFamily);
} finally {
textBox.set('fontFamily', fontFamily);
}
}

canvas.add(textBox);
canvas.requestRenderAll();

return textBox;
}
65 changes: 65 additions & 0 deletions src/fabritor/UI/panel/TextPanel/PresetFontPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Flex, Card, Typography } from 'antd';

const { Title } = Typography;

const PRESET_FONT_LIST = [
{
label: <div style={{ fontSize: 30, fontWeight: 'bold' }}>添加标题</div>,
key: 'title',
config: {
fontFamily: 'Times New Roman',
fontWeight: 'bold',
fontSize: 100,
text: '添加标题',
top: 100
}
},
{
label: <div style={{ fontSize: 24, fontFamily: 'AlibabaPuHuiTi' }}>添加副标题</div>,
key: 'sub-title',
config: {
fontFamily: 'AlibabaPuHuiTi',
fontWeight: 'bold',
fontSize: 75,
text: '添加副标题',
top: 200
}
},
{
label: <div style={{ fontSize: 16, fontFamily: 'AlibabaPuHuiTi' }}>添加一段正文</div>,
key: 'content',
config: {
fontFamily: 'AlibabaPuHuiTi',
fontSize: 50,
text: '添加一段正文'
}
}
]

export default function PresetFontPanel (props) {
const { addTextBox } = props;

const handleClick = (item) => {
addTextBox?.(item.config);
}

return (
<Flex vertical gap={8} style={{ marginTop: 16 }}>
<Title level={4}>默认文字样式</Title>
{
PRESET_FONT_LIST.map(item => (
<Card
key={item.key}
hoverable
onClick={() => { handleClick(item) }}
bodyStyle={{
padding: '12px 30px'
}}
>
{item.label}
</Card>
))
}
</Flex>
);
}
16 changes: 13 additions & 3 deletions src/fabritor/UI/panel/TextPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,32 @@ import { useContext } from 'react';
import { Button } from 'antd';
import { getGlobalEditor } from '@/utils/global';
import { GloablStateContext } from '@/context';
import PresetFontPanel from './PresetFontPanel';
import { createTextbox } from '@/editor/textbox';

export default function TextPanel () {
const { setActiveObject } = useContext(GloablStateContext);

const handleAddText = async () => {
const handleAddText = async (options) => {
const editor = getGlobalEditor();
const textbox = await editor.addTextbox();
const textbox = await createTextbox(options);
editor.canvas.setActiveObject(textbox);
setActiveObject(textbox);
}

// const clear = () => {
// const editor = getGlobalEditor();
// editor.canvas.discardActiveObject();
// editor.canvas.requestRenderAll();
// setActiveObject(null);
// }

return (
<div className="fabritor-panel-text-wrapper">
<Button type="primary" block onClick={handleAddText}>
<Button type="primary" block onClick={() => { handleAddText({}) }} size="large">
添加文本框
</Button>
<PresetFontPanel addTextBox={handleAddText} />
</div>
)
}
13 changes: 13 additions & 0 deletions src/fabritor/UI/setter/TextSetter/ColorSetter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ColorPicker } from 'antd';

export default function AlignSetter (props) {
const { value, onChange, ...rest } = props;

const handleChange = (v) => {
onChange && onChange(v.toHexString())
}

return (
<ColorPicker value={value} onChange={handleChange} format="hex" showText {...rest} />
)
}
45 changes: 38 additions & 7 deletions src/fabritor/UI/setter/TextSetter/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
import { useContext, useEffect } from 'react';
import { Form, Radio, InputNumber, ColorPicker, Select } from 'antd';
import { Form, InputNumber, Select, Switch } from 'antd';
import { FONT_PRESET_FAMILY_LIST } from '@/utils/constants';
import { GloablStateContext } from '@/context';
import FontStyleSetter from './FontStyleSetter';
import AlignSetter from './AlignSetter';
import ColorSetter from './ColorSetter';
import { loadFont } from '@/utils';
import { getGlobalEditor } from '@/utils/global';

const { Item: FormItem } = Form;

export default function TextSetter (props) {
export default function TextSetter () {
const { object } = useContext(GloablStateContext);
const [form] = Form.useForm();

const handleValuesChange = (values) => {

const handleFontStyles = (styles) => {
object.set('fontWeight', styles?.bold ? 'bold' : 'normal');
object.set('fontStyle', styles?.italic ? 'italic' : 'normal');
object.set('underline', !!styles.underline);
object.set('linethrough', !!styles.linethrough);
}

const handleValuesChange = async (values) => {
console.log(values);
const keys = Object.keys(values);
if (!keys?.length) return;

for (let key of keys) {
if (key === 'fontStyles') {
handleFontStyles(values[key]);
} else if (key === 'fontFamily') {
try {
await loadFont(values[key]);
} finally {
object.set(key, values[key]);
}
return;
} else {
object.set(key, values[key]);
}
}

const editor = getGlobalEditor();
editor.canvas.requestRenderAll();
}

useEffect(() => {
Expand Down Expand Up @@ -42,7 +72,9 @@ export default function TextSetter (props) {
label="字体"
name="fontFamily"
>
<Select options={FONT_PRESET_FAMILY_LIST} />
<Select
options={[{ label: '系统默认', value: 'Times New Roman' }, ...FONT_PRESET_FAMILY_LIST]}
/>
</FormItem>
<FormItem
label="字号"
Expand All @@ -60,7 +92,7 @@ export default function TextSetter (props) {
label="颜色"
name="fill"
>
<ColorPicker />
<ColorSetter />
</FormItem>
<FormItem
label="对齐"
Expand All @@ -74,7 +106,6 @@ export default function TextSetter (props) {
>
<FontStyleSetter />
</FormItem>
{/*竖版*/}
{/*特效*/}
</Form>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const TEXTBOX_DEFAULT_CONFIG = {
// styles
fill: '#000000',
fontWeight: 'normal',
fontSize: 80,
fontSize: 50,
lineHeight: 1.30,
textAlign: 'center',
fontFamily: 'AlibabaPuHuiTi',
Expand Down

0 comments on commit 0ac00c4

Please sign in to comment.