#javascript #jquery #canvas #fabricjs
#javascript #jquery #холст #fabricjs
Вопрос:
Я пытаюсь создать инструмент с квадратной изогнутой стрелкой.
Я использовал демонстрацию по следующей ссылке для создания инструмента. http://kpomservices.com/oldweb/HTML5_Canvas_Curved_Lines.php
мне удалось создать инструмент, который мне нужен. но у меня возникают некоторые проблемы с этим. Надеюсь, что кто-нибудь здесь сможет мне помочь в этом вопросе… вот код, который я использую для создания инструмента..
line_number ;
var line;
var reinit_stroke = "";
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
function _getQBezierValue(t, p1, p2, p3) {
var iT = 1 - t;
return iT * iT * p1 2 * iT * t * p2 t * t * p3;
}
function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
return {
x: _getQBezierValue(position, startX, cpX, endX),
y: _getQBezierValue(position, startY, cpY, endY)
};
}
canvas.on({
'object:selected': onObjectSelected,
'object:moving': onObjectMoving,
'before:selection:cleared': onBeforeSelectionCleared
});
(function drawQuadratic() {
line = new fabric.Path('M 65 0 Q 100, 100, 200, 0', { fill: '', selectable: false,hasBorders: false,hasControls: false,stroke: #000});
line.path[0][1] = posx;
line.path[0][2] = posy;
line.path[1][1] = posx 50;
line.path[1][2] = posy 50;
line.path[1][3] = posx 100;
line.path[1][4] = posy 100;
line.id = line_number;
//line.selectable = false;
canvas.add(line);
canvas.sendBackwards(line);
var pt = getQuadraticCurvePoint(line.path[0][1], line.path[0][2], line.path[1][1], line.path[1][2], line.path[1][3], line.path[1][4], 0.5);
var p1 = makeCurvePoint(pt.x, pt.y, null, line, null)
p1.name = "p1";
p1.id = line_number;
canvas.add(p1);
var p0 = makeCurveCircle(posx, posy, line, p1, null);
p0.name = "p0";
p0.id = line_number;
canvas.add(p0);
var p2 = makeArrow(posx 100, posy 100, null, p1, line);
p2.name = "p2";
p2.id = line_number;
canvas.add(p2);
var dx = line.path[1][3] - posx;
var dy = line.path[1][4] - posy;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
p2.setAngle(angle 90);
p2.setCoords();
canvas.bringToFront(p2);
canvas.bringToFront(p0);
canvas.bringToFront(p1);
line.p2 = p2;
})();
function makeArrow(left, top, line1, line2, line3) {
var c = new fabric.Triangle({
width: 5,
height: 5,
left: left 5,
top: top 5,
strokeWidth: 10,
fill: #000,
opacity: 1,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.angle = 90;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
function makeCurveCircle(left, top, line1, line2, line3) {
var c = new fabric.Circle({
radius: 5,
left: left,
top: top,
strokeWidth: 10,
fill: #000,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
function makeCurvePoint(left, top, line1, line2, line3) {
var c = new fabric.Circle({
radius: 5,
left: left,
top: top,
strokeWidth: 10,
fill: #000,
opacity: 0,
stroke: #000
});
c.hasBorders = c.hasControls = false;
c.angle = 90;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
return c;
}
var prevselobj;
function onObjectSelected(e) {
var activeObject = e.target;
reinit_stroke = activeObject.stroke;
if (activeObject.name == "p0" || activeObject.name == "p2") {
if (prevselobj) {
prevselobj.line2.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
prevselobj.line2.selectable = false;
}
activeObject.line2.animate('opacity', '1', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.line2.selectable = true;
prevselobj = activeObject;
}
}
function onBeforeSelectionCleared(e) {
var activeObject = e.target;
if (activeObject.name == "p0" || activeObject.name == "p2") {
activeObject.line2.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.line2.selectable = false;
}
else if (activeObject.name == "p1") {
activeObject.animate('opacity', '0', {
duration: 200,
onChange: canvas.renderAll.bind(canvas),
});
activeObject.selectable = true;
}
}
function onObjectMoving(e) {
if (e.target.name == "p0" || e.target.name == "p2") {
var p = e.target;
var curvedline;
if (p.line1) {
p.line1.path[0][1] = p.left;
p.line1.path[0][2] = p.top p.height/2;
curvedline = p.line1;
} else if (p.line3) {
p.line3.path[1][3] = p.left;
if(p.line3.path[0][2] <= p.line3.path[1][4])
p.line3.path[1][4] = p.top - p.height/2;
if(p.line3.path[0][2] > p.line3.path[1][4])
p.line3.path[1][4] = p.top p.height/2;
p.line3.setCoords();
curvedline = p.line3;
}
if (curvedline) {
curvedline.setCoords();
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.5);
p.line2.left = pt.x;
p.line2.top = pt.y;
if (curvedline.p2) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.99);
curvedline.p2.left = pt.x;
curvedline.p2.top = pt.y;
var dx = curvedline.path[1][3] - pt.x;
var dy = curvedline.path[1][4] - pt.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
curvedline.p2.setAngle(angle 90);
curvedline.p2.setCoords();
}
p.line2.setCoords();
}
if (e.target.text) {
e.target.text.left = p.left;
e.target.text.top = p.top;
e.target.text.setCoords();
}
} else if (e.target.name == "p1") {
var p = e.target;
if (p.line2) {
p.line2.path[1][1] = p.left;
p.line2.path[1][2] = p.top;
}
curvedline = p.line2;
if (curvedline) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.5);
p.left = pt.x;
p.top = pt.y;
p.setCoords();
}
if (curvedline) {
var pt = getQuadraticCurvePoint(curvedline.path[0][1], curvedline.path[0][2], curvedline.path[1][1], curvedline.path[1][2], curvedline.path[1][3], curvedline.path[1][4], 0.99);
curvedline.p2.left = pt.x;
curvedline.p2.top = pt.y;
var dx = curvedline.path[1][3] - pt.x;
var dy = curvedline.path[1][4] - pt.y;
var angle = Math.atan2(dy, dx) * 180 / Math.PI;
curvedline.p2.setAngle(angle 90);
curvedline.p2.setCoords();
}
} else if (e.target.name == "p0" || e.target.name == "p2") {
var p = e.target;
p.line1 amp;amp; p.line1.set({
'x2': p.left,
'y2': p.top
});
p.line2 amp;amp; p.line2.set({
'x1': p.left,
'y1': p.top
});
p.line3 amp;amp; p.line3.set({
'x1': p.left,
'y1': p.top
});
p.line4 amp;amp; p.line4.set({
'x1': p.left,
'y1': p.top
});
}
p amp;amp; reinit();
}
function reinit() {
canvas.remove(line);
line = new fabric.Path(line.path, { fill: '',selectable: false });
line.id = line_number;
line.stroke = reinit_stroke;
canvas.add(line);
canvas.sendBackwards(line);
}
canvas.on('mouse:over', function(e) {
if(e.target.type == "path")
{
canvas.sendBackwards(e.target);
}
});
Я использую следующий код для удаления инструмента.
(Примечание: этот код запускается, когда я нажимаю на кнопку удаления. Кнопка удаления удаляет выбранный объект. )
вот код…
var objs = canvas.getObjects();
if (activeObject) {
active_id = activeObject.get('id');
canvas.forEachObject(function (obj) {
if(obj.get('id') == active_id)
{
if(obj.type == 'path')
{
obj.selectable = true;
canvas.remove(obj);
}
canvas.remove(obj);
}
});
canvas.remove(activeObject);
}
проблема, с которой я сталкиваюсь, заключается в том, что после удаления этого, если я создам еще одну изогнутую стрелку в конструкторе (т. Е. Без перезагрузки страницы) и перемещаю узлы, тогда он все еще показывает старый объект path, который мы уже удалили.
и если я удалю вновь созданную изогнутую стрелку, то она удалит весь путь с холста, короче говоря, все объекты Path ведут себя как один (надеюсь, это понятно).).
итак, объект path не удаляется должным образом, он просто скрывается, когда я его удаляю. Или, может быть, он удален, но создан снова, когда я перемещаю другой объект path.. и если мы сохраним холст как json, тогда мы сможем увидеть объекты path, которые тоже будут удалены.
Что мне нужно сделать, так это правильно удалить объект path и сохранить только объект Path, который в данный момент отображается на холсте с узлами.
Пожалуйста, скажите мне, есть ли какое-то решение для этой проблемы..
Спасибо..
Ответ №1:
Я нашел решение проблемы с удалением кривой. Нам нужно изменить код в функциях reinit() . Он перезаписал line_id для всей строки (или, скажем, пути) на холсте. Вот код для замены на функцию reinit() ..
function reinit() {
var objs = canvas.getObjects();
current_line = canvas.getActiveObject();
canvas.forEachObject(function (obj) {
if(obj.type == 'path' amp;amp; obj.get("id") == current_line.get("id"))
{
canvas.remove(obj);
line = new fabric.Path(obj.path, { fill: '',selectable: false });
line.id = current_line.get("id");
line.stroke = reinit_stroke;
canvas.add(line);
canvas.sendBackwards(line);
}
});
}
Надеюсь, это может быть полезно для тех, кому нужно такое решение..