gpt4 book ai didi

javascript - Fabricjs 中的箭头

转载 作者:行者123 更新时间:2023-12-02 16:00:38 31 4
gpt4 key购买 nike

我正在尝试使用fabricjs 创建一个箭头形状。到目前为止,我最好的方法是添加一条线和一个三 Angular 形,并将它们组合成一个复合组。然而问题是,当我调整箭头大小时,箭头会被拉伸(stretch),效果不佳。

我要问的是,如何在fabricjs上创建一个箭头对象,该对象只能纵向调整大小而不拉伸(stretch)箭头。 http://jsfiddle.net/skela/j45czqge/

<html>
<head>
<script src='http://fabricjs.com/build/files/text,gestures,easing,parser,freedrawing,interaction,serialization,image_filters,gradient,pattern,shadow,node.js'></script> <meta charset="utf-8">

<style>
html,body
{
height: 100%; min-height:100%;
width: 100%; min-width:100%;
background-color:transparent;
margin:0;
}
button
{
height:44px;
margin:0;
}
</style>

</head>
<body>

<span id="dev">
<button id="draw_mode" onclick="toggleDraw()">Draw</button>
<button onclick="addRect()">Add Rect</button>
<button onclick="addCircle()">Add Circle</button>
<button onclick="addTriangle()">Add Triangle</button>
<button onclick="addLine()">Add Line</button>
<button onclick="addArrow()">Add Arrow</button>
<button onclick="clearCanvas()">Clear</button>
<button onclick="saveCanvas()">Save</button>
<button onclick="loadCanvas()">Load</button>
</span>
<span id="selected" style="visibility:hidden;">
<button onclick="removeSelected()">Remove</button>
</span>
<canvas id="c" style="border:1px solid #aaa;"></canvas>

<script>

fabric.Object.prototype.toObject = (function (toObject)
{
return function ()
{
return fabric.util.object.extend(toObject.call(this),
{
id:this.id,
});
};
})(fabric.Object.prototype.toObject);

fabric.LineArrow = fabric.util.createClass(fabric.Line, {

type: 'lineArrow',

initialize: function(element, options) {
options || (options = {});
this.callSuper('initialize', element, options);
},

toObject: function() {
return fabric.util.object.extend(this.callSuper('toObject'));
},

_render: function(ctx){
this.callSuper('_render', ctx);

// do not render if width/height are zeros or object is not visible
if (this.width === 0 || this.height === 0 || !this.visible) return;

ctx.save();

var xDiff = this.x2 - this.x1;
var yDiff = this.y2 - this.y1;
var angle = Math.atan2(yDiff, xDiff);
ctx.translate((this.x2 - this.x1) / 2, (this.y2 - this.y1) / 2);
ctx.rotate(angle);
ctx.beginPath();
//move 10px in front of line to start the arrow so it does not have the square line end showing in front (0,0)
ctx.moveTo(10,0);
ctx.lineTo(-20, 15);
ctx.lineTo(-20, -15);
ctx.closePath();
ctx.fillStyle = this.stroke;
ctx.fill();

ctx.restore();

}
});

fabric.LineArrow.fromObject = function (object, callback) {
callback && callback(new fabric.LineArrow([object.x1, object.y1, object.x2, object.y2],object));
};

fabric.LineArrow.async = true;

var canvas = new fabric.Canvas('c');
canvas.isDrawingMode = false;
canvas.freeDrawingBrush.width = 5;
setColor('red');

var sendToApp = function(_key, _val)
{
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", _key + ":##drawings##" + _val);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
};

canvas.on('object:selected',function(options)
{
if (options.target)
{
//console.log('an object was selected! ', options.target.type);
var sel = document.getElementById("selected");
sel.style.visibility = "visible";
sendToApp("object:selected","");
}
});

canvas.on('selection:cleared',function(options)
{
//console.log('selection cleared');
var sel = document.getElementById("selected");
sel.style.visibility = "hidden";
sendToApp("selection:cleared","");
});

canvas.on('object:modified',function(options)
{
if (options.target)
{
//console.log('an object was modified! ', options.target.type);
sendToApp("object:modified","");
}
});

canvas.on('object:added',function(options)
{
if (options.target)
{
if (typeof options.target.id == 'undefined')
{
options.target.id = 1337;
}
//console.log('an object was added! ', options.target.type);
sendToApp("object:added","");
}
});

canvas.on('object:removed',function(options)
{
if (options.target)
{
//console.log('an object was removed! ', options.target.type);
sendToApp("object:removed","");
}
});

window.addEventListener('resize', resizeCanvas, false);

function resizeCanvas()
{
canvas.setHeight(window.innerHeight);
canvas.setWidth(window.innerWidth);
canvas.renderAll();
}

function color()
{
return canvas.freeDrawingBrush.color;
}

function setColor(color)
{
canvas.freeDrawingBrush.color = color;
}

function toggleDraw()
{
setDrawingMode(!canvas.isDrawingMode);
}

function setDrawingMode(isDrawingMode)
{
canvas.isDrawingMode = isDrawingMode;
var btn = document.getElementById("draw_mode");
btn.innerHTML = canvas.isDrawingMode ? "Drawing" : "Draw";
sendToApp("mode",canvas.isDrawingMode ? "drawing" : "draw");
}

function setLineControls(line)
{
line.setControlVisible("tr",false);
line.setControlVisible("tl",false);
line.setControlVisible("br",false);
line.setControlVisible("bl",false);
line.setControlVisible("ml",false);
line.setControlVisible("mr",false);
}

function createLine(points)
{
var line = new fabric.Line(points,
{
strokeWidth: 5,
stroke: color(),
originX: 'center',
originY: 'center',
lockScalingX:true,
//lockScalingY:false,
});
setLineControls(line);
return line;
}

function createArrowHead(points)
{
var headLength = 15,

x1 = points[0],
y1 = points[1],
x2 = points[2],
y2 = points[3],

dx = x2 - x1,
dy = y2 - y1,

angle = Math.atan2(dy, dx);

angle *= 180 / Math.PI;
angle += 90;

var triangle = new fabric.Triangle({
angle: angle,
fill: color(),
top: y2,
left: x2,
height: headLength,
width: headLength,
originX: 'center',
originY: 'center',
// lockScalingX:false,
// lockScalingY:true,
});

return triangle;
}

function addRect()
{
canvas.add(new fabric.Rect({left:100,top:100,fill:color(),width:50,height:50}));
}

function addCircle()
{
canvas.add(new fabric.Circle({left:150,top:150,fill:color(),radius:50/2}));
}

function addTriangle()
{
canvas.add(new fabric.Triangle({left:200,top:200,fill:color(),height:50,width:46}));
}

function addLine()
{
var line = createLine([100,100,100,200]);
canvas.add(line);
}

function addArrow()
{
var pts = [100,100,100,200];
var triangle = createArrowHead(pts);
var line = createLine(pts);
var grp = new fabric.Group([triangle,line]);
setLineControls(grp);
canvas.add(grp);
// var arrow = new fabric.LineArrow(pts,{left:100,top:100,fill:color()});
// setLineControls(arrow);
// canvas.add(arrow);
}

function removeSelected()
{
var grp = canvas.getActiveGroup();
var obj = canvas.getActiveObject();
if (obj!=null)
{
canvas.remove(obj);
}
if (grp!=null)
{
grp.forEachObject(function(o){ canvas.remove(o) });
canvas.discardActiveGroup().renderAll();
}
}

function clearCanvas()
{
canvas.clear();
}

function saveCanvas()
{
var js = JSON.stringify(canvas);
return js;
}

function loadCanvas()
{
var js = '{"objects":[{"type":"circle","originX":"left","originY":"top","left":150,"top":150,"width":50,"height":50,"fill":"red","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","id":1234,"radius":25,"startAngle":0,"endAngle":6.283185307179586}],"background":""}';
canvas.loadFromJSON(js);
}

resizeCanvas();

</script>
</body>
</html>

最佳答案

我遇到了同样的问题,最终进行数学计算来计算围绕直线组成箭头形状的点,并使用多边形对象代替。

它的核心看起来像:

var angle = Math.atan2(toy - fromy, tox - fromx);

var headlen = 15; // arrow head size

// bring the line end back some to account for arrow head.
tox = tox - (headlen) * Math.cos(angle);
toy = toy - (headlen) * Math.sin(angle);

// calculate the points.
var points = [
{
x: fromx, // start point
y: fromy
}, {
x: fromx - (headlen / 4) * Math.cos(angle - Math.PI / 2),
y: fromy - (headlen / 4) * Math.sin(angle - Math.PI / 2)
},{
x: tox - (headlen / 4) * Math.cos(angle - Math.PI / 2),
y: toy - (headlen / 4) * Math.sin(angle - Math.PI / 2)
}, {
x: tox - (headlen) * Math.cos(angle - Math.PI / 2),
y: toy - (headlen) * Math.sin(angle - Math.PI / 2)
},{
x: tox + (headlen) * Math.cos(angle), // tip
y: toy + (headlen) * Math.sin(angle)
}, {
x: tox - (headlen) * Math.cos(angle + Math.PI / 2),
y: toy - (headlen) * Math.sin(angle + Math.PI / 2)
}, {
x: tox - (headlen / 4) * Math.cos(angle + Math.PI / 2),
y: toy - (headlen / 4) * Math.sin(angle + Math.PI / 2)
}, {
x: fromx - (headlen / 4) * Math.cos(angle + Math.PI / 2),
y: fromy - (headlen / 4) * Math.sin(angle + Math.PI / 2)
},{
x: fromx,
y: fromy
}
];

然后从这些点创建一个多边形。

https://jsfiddle.net/6e17oxc3/

关于javascript - Fabricjs 中的箭头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31238010/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com