Skip to content

Commit

Permalink
feat: 新增细尾箭头绘制元素(thinTailArrow) (#382)
Browse files Browse the repository at this point in the history
* feat: 新增细尾箭头绘制元素(thinTailArrow)

* fix: 细尾箭头样式调整
  • Loading branch information
wuchenguang1998 authored May 11, 2024
1 parent 2a3f9a4 commit bc2cc82
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 18 deletions.
57 changes: 57 additions & 0 deletions packages/core/objects/ThinTailArrow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* @Author: wuchenguang1998
* @Date: 2024-05-10 10:46:10
* @LastEditors: wuchenguang1998
* @LastEditTime: 2024-05-10 22:08:51
* @Description: 细尾箭头,支持控制条拖拽不变形
*/
import { fabric } from 'fabric';

fabric.ThinTailArrow = fabric.util.createClass(fabric.Line, {
type: 'thinTailArrow',
superType: 'drawing',
initialize(points, options) {
if (!points) {
const { x1, x2, y1, y2 } = options;
points = [x1, y1, x2, y2];
}
options = options || {};
this.callSuper('initialize', points, options);
},
_render(ctx) {
ctx.save();
// 乘或除对应的scaleX(Y),抵消元素放缩造成的影响,使箭头不会变形
ctx.scale(1 / this.scaleX, 1 / this.scaleY);
const xDiff = (this.x2 - this.x1) * this.scaleX;
const yDiff = (this.y2 - this.y1) * this.scaleY;
ctx.translate(-xDiff / 2, -yDiff / 2);
// 箭头方位角
const angle = Math.atan2(yDiff, xDiff);
ctx.rotate(angle);
// 箭头总长(最小长度是20)
let length = Math.hypot(xDiff, yDiff);
length = length < 20 ? 20 : length;
// 绘制箭头
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(length - 18, -5);
ctx.lineTo(length - 20, -12);
ctx.lineTo(length, 0);
ctx.lineTo(length - 20, 12);
ctx.lineTo(length - 18, 5);
ctx.lineTo(0, 0);
ctx.lineWidth = this.strokeWidth;
ctx.strokeStyle = this.stroke;
ctx.fillStyle = this.fill;
ctx.stroke();
ctx.fill();
ctx.restore();
},
});

fabric.ThinTailArrow.fromObject = (options, callback) => {
const { x1, x2, y1, y2 } = options;
return callback(new fabric.ThinTailArrow([x1, y1, x2, y2], options));
};

export default fabric.ThinTailArrow;
43 changes: 33 additions & 10 deletions packages/core/plugin/DrawLinePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@
import { v4 as uuid } from 'uuid';
import { fabric } from 'fabric';
import Arrow from '../objects/Arrow';
import ThinTailArrow from '../objects/ThinTailArrow';
import Editor from '../Editor';
type IEditor = Editor;

class DrawLinePlugin {
public canvas: fabric.Canvas;
public editor: IEditor;
static pluginName = 'DrawLinePlugin';
static apis = ['setArrow', 'setMode'];
static apis = ['setLineType', 'setMode'];
isDrawingLineMode: boolean;
isArrow: boolean;
lineType: string;
lineToDraw: any;
pointer: any;
pointerPoints: any;
Expand All @@ -29,7 +30,7 @@ class DrawLinePlugin {

this.isDrawingLine = false;
this.isDrawingLineMode = false;
this.isArrow = false;
this.lineType = '';
this.lineToDraw = null;
this.pointer = null;
this.pointerPoints = null;
Expand All @@ -49,13 +50,34 @@ class DrawLinePlugin {
this.isDrawingLine = true;
this.pointer = canvas.getPointer(o.e);
this.pointerPoints = [this.pointer.x, this.pointer.y, this.pointer.x, this.pointer.y];

const NodeHandler = this.isArrow ? Arrow : fabric.Line;
this.lineToDraw = new NodeHandler(this.pointerPoints, {
let NodeHandler;
let opts: any = {
strokeWidth: 2,
stroke: '#000000',
id: uuid(),
});
};
switch (this.lineType) {
case 'line':
NodeHandler = fabric.Line;
break;
case 'arrow':
NodeHandler = Arrow;
break;
case 'thinTailArrow':
NodeHandler = ThinTailArrow;
opts = {
strokeWidth: 2,
stroke: '#ff0000',
fill: '#ff0000',
id: uuid(),
};
break;
default:
break;
}
if (!NodeHandler) throw new Error('Draw failed: invalid lineType.');

this.lineToDraw = new NodeHandler(this.pointerPoints, opts);

this.lineToDraw.selectable = false;
this.lineToDraw.evented = false;
Expand All @@ -64,7 +86,8 @@ class DrawLinePlugin {
});

canvas.on('mouse:move', (o) => {
if (!this.isDrawingLine) return;
if (!this.isDrawingLine || !['line', 'arrow', 'thinTailArrow'].includes(this.lineType))
return;
canvas.discardActiveObject();
const activeObject = canvas.getActiveObject();
if (activeObject) return;
Expand Down Expand Up @@ -105,8 +128,8 @@ class DrawLinePlugin {
});
}

setArrow(params: any) {
this.isArrow = params;
setLineType(params: any) {
this.lineType = params;
}

setMode(params: any) {
Expand Down
1 change: 1 addition & 0 deletions src/components/attribute.vue
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ const baseType = [
'group',
'line',
'arrow',
'thinTailArrow',
];
// 文字元素
const textType = ['i-text', 'textbox', 'text'];
Expand Down
37 changes: 29 additions & 8 deletions src/components/tools.vue
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@
<Divider plain orientation="left">{{ $t('draw_elements') }}</Divider>
<div class="tool-box">
<span
@click="drawingLineModeSwitch(false)"
:class="state.isDrawingLineMode && !state.isArrow && 'bg'"
@click="drawingLineModeSwitch('line')"
:class="state.isDrawingLineMode && state.lineType === 'line' && 'bg'"
>
<svg
t="1673022047861"
Expand All @@ -135,8 +135,8 @@
</svg>
</span>
<span
@click="drawingLineModeSwitch(true)"
:class="state.isDrawingLineMode && state.isArrow && 'bg'"
@click="drawingLineModeSwitch('arrow')"
:class="state.isDrawingLineMode && state.lineType === 'arrow' && 'bg'"
>
<!-- <svg t="1673022047861" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4206" width="20" height="20"><path d="M187.733333 1024h-170.666666c-10.24 0-17.066667-6.826667-17.066667-17.066667v-170.666666c0-10.24 6.826667-17.066667 17.066667-17.066667h170.666666c10.24 0 17.066667 6.826667 17.066667 17.066667v170.666666c0 10.24-6.826667 17.066667-17.066667 17.066667zM34.133333 989.866667h136.533334v-136.533334H34.133333v136.533334zM1006.933333 204.8h-170.666666c-10.24 0-17.066667-6.826667-17.066667-17.066667v-170.666666c0-10.24 6.826667-17.066667 17.066667-17.066667h170.666666c10.24 0 17.066667 6.826667 17.066667 17.066667v170.666666c0 10.24-6.826667 17.066667-17.066667 17.066667zM853.333333 170.666667h136.533334V34.133333h-136.533334v136.533334z" fill="" p-id="4207"></path><path d="M187.733333 853.333333c-3.413333 0-10.24 0-13.653333-3.413333-6.826667-6.826667-6.826667-17.066667 0-23.893333l648.533333-648.533334c6.826667-6.826667 17.066667-6.826667 23.893334 0s6.826667 17.066667 0 23.893334l-648.533334 648.533333c0 3.413333-6.826667 3.413333-10.24 3.413333z" fill="" p-id="4208"></path></svg> -->
<svg
Expand All @@ -156,6 +156,27 @@
></path>
</svg>
</span>
<span
@click="drawingLineModeSwitch('thinTailArrow')"
:class="state.isDrawingLineMode && state.lineType === 'thinTailArrow' && 'bg'"
>
<svg
t="1715323097309"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="24572"
width="20"
height="20"
>
<path
d="M485.954269 735.978673 643.38051 811.107852C688.831327 832.798434 686.17686 860.459274 635.3838 871.903075L81.378406 996.721881C31.19882 1008.027444-1.313538 976.266799 10.130269 925.473745L134.949081 371.468357C146.254656 321.288783 173.611855 317.095036 195.744311 363.471653L270.873453 520.897858 903.670271 62.052983C986.301645 2.136458 1004.805285 20.426857 944.799125 103.181838L485.954269 735.978673Z"
fill="#444444"
p-id="24573"
></path>
</svg>
</span>
</div>
</div>
</template>
Expand All @@ -178,7 +199,7 @@ const { t } = useI18n();
const { fabric, canvasEditor } = useSelect();
const state = reactive({
isDrawingLineMode: false,
isArrow: false,
lineType: false,
});
// let drawHandler = null;
Expand Down Expand Up @@ -297,11 +318,11 @@ const addRect = (option) => {
}
canvasEditor.canvas.setActiveObject(rect);
};
const drawingLineModeSwitch = (isArrow) => {
state.isArrow = isArrow;
const drawingLineModeSwitch = (type) => {
state.lineType = type;
state.isDrawingLineMode = !state.isDrawingLineMode;
canvasEditor.setMode(state.isDrawingLineMode);
canvasEditor.setArrow(isArrow);
canvasEditor.setLineType(type);
// this.canvasEditor.setMode(this.isDrawingLineMode);
// this.canvasEditor.setArrow(isArrow);
Expand Down

0 comments on commit bc2cc82

Please sign in to comment.